Нажатие на элемент сетки данных WPF не отражается в наблюдаемой коллекции в модели представления. - PullRequest
0 голосов
/ 06 июня 2018

У меня есть приложение WPF MVVM, у которого есть сетка данных WPF Toolkit, связанная с наблюдаемой коллекцией.Один из столбцов - это DataGridTemplateColumn, который реализует столбец переключаемых кнопок:

<dg:DataGrid ItemsSource="{Binding Path=LlistatDocuments}"                
             AutoGenerateColumns="False"
             CanUserAddRows="False" CanUserResizeRows="False"
             SelectionMode="Single"                 
             ColumnWidth="*"
             AlternationCount="2" AlternatingRowBackground="Bisque" 
             Focusable="False" SelectionUnit="FullRow"
             CellStyle="{StaticResource Body_Content_DataGrid_Centering}"
             GridLinesVisibility="All">

   <dg:DataGrid.Resources>
         <proxy:BindingProxy x:Key="myProxy" Data="{Binding}" />
   </dg:DataGrid.Resources>

   <dg:DataGrid.Columns>

         <dg:DataGridTemplateColumn Header="Selection" 
                                    MinWidth="65" Width="Auto" 
                                    CanUserResize="False">

            <dg:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ToggleButton Background="Transparent" Content="" IsChecked="{Binding Path=Data.IsSelected, Source={StaticResource myProxy}, Mode=TwoWay}" BorderBrush="Transparent">
                        <ToggleButton.Template>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <StackPanel Orientation="Horizontal" Background="Transparent">
                                    <Image MaxWidth="32" MaxHeight="32">
                                        <Image.Style>
                                            <Style>
                                                <Setter Property="Image.Source" Value="/My.App.Graphics;component/Images/Unchecked.png" />
                                                <Style.Triggers>
                                                    <DataTrigger Binding="{Binding IsChecked, 
                                                                           RelativeSource={RelativeSource  Mode=FindAncestor, 
                                                                                           AncestorType={x:Type ToggleButton}}}" Value="True">
                                                        <Setter Property="Image.Source" Value="/DiR.Utilitats.RecursosGrafics;component/PNG/Checked.png" />
                                                    </DataTrigger>
                                                </Style.Triggers>
                                            </Style>
                                        </Image.Style>
                                    </Image>
                                    <ContentPresenter Content="{TemplateBinding Content}" Margin="0,0,0,0" />
                                </StackPanel>
                            </ControlTemplate>
                        </ToggleButton.Template>
                    </ToggleButton>
                </DataTemplate>
            </dg:DataGridTemplateColumn.CellTemplate>

         </dg:DataGridTemplateColumn>
   </dg:DataGrid.Columns>
</dg:DataGrid

Модель :

public class MyModel
{
    public int Id { get; set; }
    public bool IsSelected { get; set; }
}

Просмотреть модель :

private ObservableCollection<MyModel> _myDataGridItems;
public ObservableCollection<MyModel> MyDataGridItems
{
    get
    {
        return this._myDataGridItems;
    }

    set
    {
        this._myDataGridItems = value;
        OnPropertyChanged("MyDataGridItems");
    }
}

private bool _isSelected;
public bool IsSelected
{
    get
    {
        return this._isSelected;
    }

    set
    {
        this._isSelected = value;

        // Do other stuff. 
        // Here MyDataGridItems collection has not changed to selected yet for the selected item.

        OnPropertyChanged("IsSelected");
    }
}

Прокси :

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

Когда я щелкаю по элементу сетки данных (столбец DataGridTemplateColumn), свойство IsSelected правильно достигается, но в этот момент соответствующий элементв коллекции MyDataGridItems еще не было изменено на IsSelected = true или IsSelected = false.Зачем?Это изменение еще не отражено в коллекции MyDataGridItems.

1 Ответ

0 голосов
/ 06 июня 2018

Прежде всего, ваш пример кода слишком сложен: вы могли бы избавить нас от триггеров смены изображений: P

Что касается вашей проблемы, я понятия не имею, зачем вам нужен связующий прокси.

Во-вторых, ObservableCollection не будет делать то, что вы думаете.ObservableCollection уведомляет только об изменениях коллекции: добавлении новых элементов или удалении существующих, перемещении их внутри коллекции и т. Д.

Если вы хотите привязать свойства объектов внутри ObservableCollection и реагировать на их изменение в пользовательском интерфейсе, ваши объекты имеютреализовать INotifyPropertyChanged.Ваш BindingProxy пытается эмулировать это - DependencyProperties также уведомляет об изменениях.

Итак, я бы предложил переименовать MyModel в MyModetlDTO (или что-то в этом роде), а затем создать другой MyModel, свойства которого уведомляют об изменениях.Вы можете легко конвертировать их между собой, используя инструмент, подобный AutoMapper .

Затем, в вашей таблице данных, которая имеет ItemsSource, связанный с ObservableCollection (который реализует INotifyPropertyChanged), вы просто делаете:

<dg:DataGrid.Columns>

         <dg:DataGridTemplateColumn Header="Selection" 
                                    MinWidth="65" Width="Auto" 
                                    CanUserResize="False">

            <dg:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ToggleButton Background="Transparent" Content="" IsChecked="{Binding Path=IsSelected}" BorderBrush="Transparent">

и автоматически работает.

...