简体   繁体   中英

WPF 4 Datagrid with ComboBox, CollectionViewSource and Entity Framework

I have a very simple table on my SQL Server 2008 database with only two fields:

Table Name: Administrators
     Field: Id (PK with AutoIncrement)
     Field: UserLogin (nvarchar)

What I'm trying to do is create a DataGrid that will allow me to add, delete or edit data from this table, using Entity Framework to connect to the database.

What I want is for the DataGrid to show a ComboBox when editing the table (specifically for the UserLogin field), and I want this ComboBox to be populated with a list of users that will be retrieved from my company's Active Directory.

The Active Directory part of the code is done and already working.

The problem I have is that, even though I managed for the combobox to display a list of users from my AD, whenever the user presses "Enter" or clicks in another cell to commit the edit, the value selected on the combobox (or the value that the user typed, because text editing is enabled in the combobox) is not being correctly set back to my EntitySet, so when the Cell leaves the Edit Mode, the value shown is a empty string (the default value when the entity is created).

Just to show you a bit of my code, I have two "CollectionViewSource" objects, one for the Administrators table and one for a List of "ActiveDirectoryUser" objects. The "ActiveDirectoryUser" is a class I wrote that holds a few information from each AD user.

Here's my code to set up the CollectionViewSource.Source properties:

// Global variable declaration
public List<ActiveDirectoryUser> adUsers = new List<ActiveDirectoryUsers>();

// The method below is called in the Window_Loaded() event
private void SetUpCollectionViewSourceBindings()
{
    adUsers = GetListOfADUsers(); // No need to show the code for the GetListOfADUsers() method

    CollectionViewSource adViewSource = (CollectionViewSource)FindResource("ADUsersSource");
    adViewSource.Source = adUsers;

    CollectionViewSource adminViewSource = (CollectionViewSource)FindResource("AdministratorsSource");
    ObjectQuery<Administrators> adminQuery = GetAdministrators();
    adminViewSource.Source = adminQuery.Execute(MergeOption.OverwriteChanges);
}

private ObjectQuery<Administrators> GetAdministrators()
{
    var adminQuery = (from admin in dbEntities.Administrators
                      select admin);
    return adminQuery as ObjectQuery<Administrators>;
}

My ActiveDirectoryUser class has only five properties:

public class ActiveDirectoryUser
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public string SAMAccountName { get; private set; } // User login information
    public string UserPrincipalName { get; private set; }
    public string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } }
}

In my XAML for the MainWindow.xaml file, I added the following CollectionViewSources to the resources:

<Window.Resources>
    <CollectionViewSource x:Key="AdministratorsSource" />
    <CollectionViewSource x:Key="ADUsersSource" />
</Window.Resources>

and then, I added the following DataGrid, with the bindings shown below:

<DataGrid x:Name="dgAdministrators"
          DataContext="{Binding Source={StaticResource AdministratorsSource}}"
          ItemsSource="{Binding}"
          AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="User Login">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=UserLogin, ValidatesOnDataErrors=True}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox IsReadOnly="False"
                              IsEditable="True"
                              IsTextSearchCaseSensitive="False"
                              IsTextSearchEnabled="True"
                              ItemsSource="{Binding Source={StaticResource ADUsersSource}}"
                              DisplayMemberPath="FullName"
                              SelectedValuePath="SAMAccountName"
                              SelectedValue="{Binding DataContext.UserLogin, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
                              SelectedItem="{Binding UserLogin}"
                              />
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

I am using .NET 4.0, and I'm using the DataGrid that comes with this version of .NET, and NOT the WPFToolkit version.

Can anyone help me finding out why the value typed in the combobox (or selected in the combobox's dropdown list) is not commiting back to my DataGrid's DataContext?

I think you have to add TwoWay binding into the ItemsSource Property. I think by default it is OneWay

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM