DataGrid DataGridTemplateColumn ComboBox

自作多情 提交于 2021-02-17 05:51:33

问题


I'm having trouble with my ComboBoxes in a DataGrid, let me explain with a few pictures.

enter image description here

This is the starting point.

enter image description here

Now if I want to add a new row I click the last row and hit Enter.

enter image description here

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.

enter image description here

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!