Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enhancing the display of a particular column in a WPF grid view

I have some user admin functionality in a WPF app that I'm currently writing and would like to make it a bit more intuitive for the end user

I'd like to be able to provide some kind of means of easily editing the list of roles a given user belongs to. At the moment the grid is filled as a result of binding to a List<ApplicationUser>

ApplicationUser is my own class defined as:

public class ApplicationUser
{
        public Guid? UserId { get; set; }
        public string GivenName { get; set; }
        public string Surname { get; set; }
        public string EmailAddress { get; set; }
        public string UserPhone { get; set; }
        public string NtLoginName { get; set; }
        public List<Role> ApplicationRoles { get; set; }
}

As can be seen the roles that the user is in are held in a List<Role>. Role is my own class defined as:

public class Role
{
   public Guid RoleId;
   public string RoleName;
   public string RoleDescription;
}

The below mockup represents the current state where I just get the roles as a List and through the use of a converter just display the roles as new-line separated strings in the gridview

Current state of gridview

However this is what I'd like to achieve to make toggling off and on membership of various groups easier.

Desired state of gridview

Now that I think about it I'll probably have to change the definition of Role to include an IsMember property to facilitate binding on the checkbox but if anybody has a better way I'll welcome that as well. I can change the JOIN type in the sproc so I get back all roles with a query about a particular user and fill the IsMember property accordingly.

Thanks for your time!

like image 419
noonand Avatar asked Jun 01 '12 16:06

noonand


2 Answers

Here is a short piece of code I've whipped up to get you started. I've assumed that you can hydrate IsMember property of Role class when you create the application user. I've taken the easiest route by having all roles in all users (enum flags would have been best but given your data, I'm not sure that's an option without some plumbing). I've used minimal columns to get the idea across. If you implement INotifyPropertyChanged on Roles at least, you can hook up to the notification and persist it back into database when the check-boxes change on front end.


Main Xaml

<DataGrid DataContext="{StaticResource ResourceKey=AllUsers}" ItemsSource="{Binding}" AutoGenerateColumns="False">
        <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding GivenName}" />
        <DataGridTextColumn Binding="{Binding Surname}" />
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding ApplicationRoles}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <CheckBox Content="{Binding RoleName}" IsChecked="{Binding IsMember, Mode=TwoWay}" />
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Data Xaml

<x:Array x:Key="AllUsers" Type="Sample:ApplicationUser">
    <Sample:ApplicationUser GivenName="Andrew" Surname="Fuller">
        <Sample:ApplicationUser.ApplicationRoles>
            <Sample:Role RoleName="Administrators" IsMember="True"/>
            <Sample:Role RoleName="Shift Analysts"/>
            <Sample:Role RoleName="Shift Managers" IsMember="True"/>
        </Sample:ApplicationUser.ApplicationRoles>
    </Sample:ApplicationUser>
    <Sample:ApplicationUser GivenName="Anne" Surname="Dodsworth">
        <Sample:ApplicationUser.ApplicationRoles>
            <Sample:Role RoleName="Administrators"/>
            <Sample:Role RoleName="Shift Analysts" IsMember="True"/>
            <Sample:Role RoleName="Shift Managers" IsMember="True"/>
        </Sample:ApplicationUser.ApplicationRoles>
    </Sample:ApplicationUser>
</x:Array>

Class definitions

public class ApplicationUser
{
    public Guid? UserId { get; set; }
    public string GivenName { get; set; }
    public string Surname { get; set; }
    public string EmailAddress { get; set; }
    public string UserPhone { get; set; }
    public string NtLoginName { get; set; }
    public List<Role> ApplicationRoles { get; set; }

    public ApplicationUser()
    {
        ApplicationRoles = new List<Role>();
    }
}

public class Role
{
    public Guid RoleId { get; set; }
    public string RoleName { get; set; }
    public string RoleDescription { get; set; }

    public bool IsMember { get; set; }
}

Result

Screenshot

like image 173
Maverik Avatar answered Oct 22 '22 03:10

Maverik


If the Roles column always displays the same list of roles, you can easily bind a ListView to the list of all roles with an ItemTemplate that is built from a CheckBox and a TextBlock.
Then, you can easily bind the IsChecked property of the CheckBox to the User Roles and use a converter that returns True if the role is in the user Roles list.

like image 33
Tamir Dresher Avatar answered Oct 22 '22 04:10

Tamir Dresher