问题
I'm having trouble with my ComboBoxes
in a DataGrid
, let me explain with a few pictures.
This is the starting point.
Now if I want to add a new row I click the last row and hit Enter.
A new row is added and iv selected type table here and given it a name MY_TABLE, then I hit enter to add another row.
The result is this, the combobox for the previous added row's type selection has gone back to None. NOTE: that the checkboxes were previously grayed out as type None cant have any privileges, but table can have CRUD
so when I selected type table they became enabled.
Here is the ViewModel (VM)
for each row:
public class RoleHasPrivilegeOnObjectEntityViewModel : EntityViewModelBase<RoleHasPrivilegeOnObjectEntityViewModel, RoleHasPrivilegesOnObject>, IRoleHasPrivilegeOnObjectListItemViewModel
{
private readonly RoleHasPrivilegesOnObject _roleHasPrivilegesOnObject;
private ObservableCollection<ObjectTypeEntityViewModel> _availableObjectTypes;
private readonly ObjectTypeEntityViewModel _objectTypeEntityViewModel;
private IRoleEntityViewModel _role;
private IObjectEntityViewModel _object;
public RoleHasPrivilegeOnObjectEntityViewModel(RoleHasPrivilegesOnObject roleHasPrivilegesOnObject, IEnumerable<OBJECT_TYPE> availableObjectTypes)
{
_roleHasPrivilegesOnObject = roleHasPrivilegesOnObject;
AvailableObjectTypes = new ObservableCollection<ObjectTypeEntityViewModel>(availableObjectTypes.Select(ot => new ObjectTypeEntityViewModel(ot)));
_role = new RoleEntityViewModel(_roleHasPrivilegesOnObject.Role);
_object = new ObjectEntityViewModel(_roleHasPrivilegesOnObject.Object);
_objectTypeEntityViewModel = new ObjectTypeEntityViewModel(_roleHasPrivilegesOnObject.Object.OBJECT_TYPE);
}
public RoleHasPrivilegeOnObjectEntityViewModel(XROLE role, CONTAINER schema, OBJECT_TYPE currentObjectType, IEnumerable<OBJECT_TYPE> availableObjectTypes)
{
var objectTypes = availableObjectTypes as IList<OBJECT_TYPE> ?? availableObjectTypes.ToList();
_roleHasPrivilegesOnObject = new RoleHasPrivilegesOnObject(role,
new XOBJECT { CONTAINER = schema, OBJECT_TYPE = currentObjectType },
new List<OBJECT_HAS_PRIVILEGE>(),
objectTypes.SelectMany(aot => aot.PRIVILEGE));
AvailableObjectTypes = new ObservableCollection<ObjectTypeEntityViewModel>(objectTypes.Select(ot => new ObjectTypeEntityViewModel(ot)));
_role = new RoleEntityViewModel(_roleHasPrivilegesOnObject.Role);
_object = new ObjectEntityViewModel(_roleHasPrivilegesOnObject.Object);
_objectTypeEntityViewModel = new ObjectTypeEntityViewModel(_roleHasPrivilegesOnObject.Object.OBJECT_TYPE);
}
public override EntityType EntityType
{
get { return SelectedObjectType.EntityType; }
}
public ObjectTypeEntityViewModel SelectedObjectType
{
get { return _objectTypeEntityViewModel; }
set
{
_roleHasPrivilegesOnObject.Object.OBJECT_TYPE = value.OriginalEntity;
OnPropertyChanged();
OnPropertyChanged("CanHaveSelect");
...
}
}
public ObservableCollection<ObjectTypeEntityViewModel> AvailableObjectTypes
{
get { return _availableObjectTypes; }
set
{
_availableObjectTypes = value;
OnPropertyChanged();
}
}
public string ToolTip
{
get { return _roleHasPrivilegesOnObject.ToolTip; }
}
public bool HasSelect
{
get { return _roleHasPrivilegesOnObject.HasSelect; }
set
{
_roleHasPrivilegesOnObject.HasSelect = value;
OnPropertyChanged();
}
}
public bool CanHaveSelect
{
get
{
var canHaveSelect = _roleHasPrivilegesOnObject.CanHaveSelect;
if(!canHaveSelect && HasSelect) HasSelect = false;
return canHaveSelect;
}
}
...
public override string NAME
{
get { return _roleHasPrivilegesOnObject.NAME; }
set
{
_roleHasPrivilegesOnObject.NAME = value;
OnPropertyChanged();
OnPropertyChanged("Text");
}
}
}
And here is my View
for the DataGrid
<UserControl ...
d:DataContext="{d:DesignInstance impl:PrivilegeDetailsViewModel}">
<UserControl.Resources>
<Style x:Key="DataGridContentCellCentering" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CanHaveSelectStyle" TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding CanHaveSelect, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding CanHaveSelect, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
...
</UserControl.Resources>
<DataGrid x:Name="PrivilegeDataGrid"
ItemsSource="{Binding RolesHasPrivilegesOnObjects}"
AutoGenerateColumns="False"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserResizeRows="False"
CanUserSortColumns="True"
CanUserAddRows="True"
IsTextSearchEnabled="True"
BorderThickness="0">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Type" CanUserSort="True" MinWidth="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type impl2:RoleHasPrivilegeOnObjectEntityViewModel}">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type impl2:ObjectTypeEntityViewModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}" ToolTip="{Binding ToolTip}" Margin="0,0,3,0" Width="17" Height="17"/>
<TextBlock Text="{Binding ToolTip}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="*" Header="Name" Binding="{Binding NAME}">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="TextBox">
<Setter Property="extensions:TextBoxUpperCaseBehavior.IsEnabled" Value="True"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<DataGridCheckBoxColumn Header="Select"
Binding="{Binding HasSelect, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
CellStyle="{StaticResource DataGridContentCellCentering}"
ElementStyle="{StaticResource CanHaveSelectStyle}"
EditingElementStyle="{StaticResource CanHaveSelectStyle}" />
...
</DataGrid.Columns>
</DataGrid>
</UserControl>
I have tried all these variants for the ComboBox
ItemsSource
and SelectedItem
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}"
SelectedValuePath="ID">
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType}">
What do I have to do to make the ComboBox
behave as expected?
回答1:
It seems that a simple UpdateSourceTrigger
attribute was missing on the SelectedObjectType
binding in the xaml
for the ComboBox
, like this
<ComboBox ItemsSource="{Binding AvailableObjectTypes}"
SelectedItem="{Binding SelectedObjectType, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding SelectedObjectType.ID}"
SelectedValuePath="ID">
来源:https://stackoverflow.com/questions/21137867/datagrid-datagridtemplatecolumn-combobox