问题
When searching for help on this topic, I typically find information on how to populate a ComboBox with related data (display name in one table for the foreign key in originating table), but I am already able to do that. I am looking for a solution on how to achieve the same result in a TextBlock.
In my project I have created a link to an SQL database using EntityFramework. There are two tables: Personnel and Role. They are related with Personnel.RoleIdFk and Role.RoleId.
I am able to get a combobox to display the Role.RoleName for the associated RoleIdFk.
In my ViewModel:
private ICollection<Role> roleList;
public ICollection<Role> RoleList
{
get { return roleList; }
set { roleList = value; NotifyPropertyChanged("RoleList"); }
}
private Role selectedRole;
public Role SelectedRole
{
get { return selectedRole; }
set { selectedRole = value; NotifyPropertyChanged("SelectedRole"); }
}
public void SetSelectedRole()
{
if (SelectedPerson == null)
{
SelectedPerson = PersonnelList.Select(p => p)
.FirstOrDefault();
}
SelectedRole = RoleList.Where(p => p.RoleId == SelectedPerson.RoleIdFk)
.FirstOrDefault();
}
And the XAML for the ComboBox:
<ComboBox x:Name="cboRole"
Grid.Column="1" Grid.Row="0"
Width="150" Height="35"
ItemsSource="{Binding RoleList}"
DisplayMemberPath="RoleName"
SelectedItem="{Binding SelectedRole}"
/>
My problem is I am also displaying a DataGrid for the Personnel table.
In this DataGrid, I would like to have the associated RoleName displayed instead of the numerical foreign key.
The current XAML for the DataGrid:
<Window.DataContext>
<viewModel:MainWindowVM />
</Window.DataContext>
<ListView Name="lstPersonnel"
Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1"
ItemContainerStyle="{StaticResource ItemContStyle}"
ItemsSource="{Binding PersonnelList}" >
<ListView.View>
<GridView>
<GridViewColumn Width="75" Header="First Name" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="75" Header="Last Name" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding LastName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="75" Header="Role" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding RoleIdFk}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
This is what the grid looks like:
For the final column, I have tried altering the text field in various ways. I have also tried using other Templates and Styles. None of these have been successful.
Is there a way to actually perform this in XAML itself, or am I going to have to set up some sort of value converter to accomplish this?
NOTE: I had thought of using some sort of "switch/case" scenario. While it would work here, I need to figure out something that can be more dynamic. Later in the project I will need to associate the PersonnelId with other items. A "switch/case" scenario is not feasible with 300+ people.
回答1:
"Role" should be available in "Personnel" object. So you can simply use "Role.RoleName" instead of "RoleIdFk":
<TextBlock Text="{Binding Role.RoleName}" />
In cases when you don't have a referenced object, it's better to join two collections and use a result as an ItemsSource of a DataGrid. Here is an example: Joining two tables in one datagrid usig Linq C# WPF
There is also a solution with IMultiValueConverter, but it seems overcomplicated: Joining 2 collections into datagrid using multibinding
来源:https://stackoverflow.com/questions/39538676/wpf-how-to-display-relational-data-in-datagrids-textblock-like-in-combobox