【问题标题】:Raise PropertyChanged in a nested ObservableCollection (a matrix of values)在嵌套的 ObservableCollection(值矩阵)中引发 PropertyChanged
【发布时间】:2014-11-27 17:19:47
【问题描述】:

嗨,我有一个绑定到 DataGrid 的对象矩阵:

在 ViewMOdel 中,矩阵本身被打包到 ObservableCollection 中:

public ObservableCollection<ObservableCollection<object>> MyMatrix {get; set;}

我的问题是当我更改 Datagrid 中的值时,这些值不会立即在绑定集合中更新。

如何让数据网格在输入一个单元格后立即更新其数据源?

这是我的代码:

XAML:

<Window x:Class="TestMatrix.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:Behaviours="clr-namespace:TestMatrix.ViewModels.Helpers.Behaviours"
        xmlns:ViewModels="clr-namespace:TestMatrix.ViewModels">

    <Window.DataContext>
        <ViewModels:MainWindowViewModel/>
    </Window.DataContext>

    <StackPanel Orientation="Vertical">
        <ToolBar VerticalAlignment="Top"            Height="Auto">
            <Button Grid.Row="1" Height="50" Width="200"  Content="Show" Command="{Binding ShowCmd}"/>
        </ToolBar>
        <ToolBar VerticalAlignment="Top"            Height="Auto">
            <TextBox Width="200" Text="{Binding Data.AString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </ToolBar>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <DataGrid AutoGenerateColumns="False"                               
                                        Width="Auto"
                                        Height="Auto"
                                        Margin="3"
                                        FontSize="15"
                                        FontWeight="Bold"
                                        CanUserAddRows="False" 
                                        CanUserDeleteRows="False"
                                        CanUserReorderColumns="False" 
                                        CanUserSortColumns="False"
                                        ItemsSource="{Binding Data.MarketerMixMatrix, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                        Behaviours:DataGridColumnsBehavior.BindableColumns="{Binding OnlineMarketerMixColumns, Mode=TwoWay}">

            </DataGrid>
        </Grid>
    </StackPanel>         </Window>

视图模型:

using Catel.MVVM;
using System;
using Catel.Data;
using TestMatrix.Models;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections.Generic;


namespace TestMatrix.ViewModels
{
    /// <summary>
    /// name view model.
    /// </summary>
    public class MainWindowViewModel : ViewModelBase
    {
        #region Properties
        /// <summary>
        /// Gets or sets the property value.
        /// </summary>
        public ObservableCollection<DataGridColumn> OnlineMarketerMixColumns
        {
            get { return GetValue<ObservableCollection<DataGridColumn>>(OnlineMarketerMixColumnsProperty); }
            set { SetValue(OnlineMarketerMixColumnsProperty, value); }
        }

        /// <summary>
        /// Register the OnlineMarketerMixColumns property so it is known in the class.
        /// </summary>
        public static readonly PropertyData OnlineMarketerMixColumnsProperty = RegisterProperty("OnlineMarketerMixColumns", typeof(ObservableCollection<DataGridColumn>), null);

        /// <summary>
        /// Gets or sets the property value.
        /// </summary>
        public ExtractedOnlineData Data
        {
            get { return GetValue<ExtractedOnlineData>(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        /// <summary>
        /// Register the Data property so it is known in the class.
        /// </summary>
        public static readonly PropertyData DataProperty = RegisterProperty("Data", typeof(ExtractedOnlineData), null);

        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindowViewModel"/> class.
        /// </summary>
        public MainWindowViewModel()
        {

            Data = new ExtractedOnlineData();

            ObservableCollection<ObservableCollection<object>> aMatrix = new ObservableCollection<ObservableCollection<object>>();
            ObservableCollection<object> innerMatrix = new ObservableCollection<object>() { 1, 2, 3, 4 };
            aMatrix.Add(innerMatrix);
            Data.MarketerMixMatrix = aMatrix;

            OnlineMarketerMixColumns = new ObservableCollection<DataGridColumn>();

            for (int i = 0; i < 4; i++)
            {
                var column = new DataGridTextColumn();

                OnlineMarketerMixColumns.Add(
                    new DataGridTextColumn
                    {
                        Header = string.Format("ColumnNumber"+i),
                        Binding = new Binding(string.Format("[{0}]", i))
                    });
            }
        }}

型号:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace TestMatrix.Models
{
    public class ExtractedOnlineData : INotifyPropertyChanged
    {
        public ExtractedOnlineData()
        {
            this.ColumnNames = new List<string>();
            this.MarketerMixMatrix = new ObservableCollection<ObservableCollection<object>>();

        }

        private ObservableCollection<ObservableCollection<object>> marketerMixMatrix;

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// Spaltenname der eingelesene Datei.
        /// </summary>
        public List<string> ColumnNames { get; set; }


        /// <summary>
        /// Vermarkter-Matrix.
        /// </summary>
        public ObservableCollection<ObservableCollection<object>> MarketerMixMatrix
        {
            get { return marketerMixMatrix; }
            set { 
                marketerMixMatrix = value;
                RaisePropertyChanged("MarketerMixMatrix");
                }
        }

        /// <summary>
        /// 
        /// </summary>
        public string AString { get; set; }
    }
}

【问题讨论】:

  • 您需要绑定事件以便在更改值时立即更新集合。您可以添加文本框的 textchange 事件以修改集合
  • 你能不能把这个范围缩小一点:"collection is updated only when i press return after the change of the values"?当您在DataGrid 中编辑单元格时,它的值会在基础集合中设置什么?完成编辑行之后?
  • @Sinatr:嗨,我的意思是,如果我在一个单元格中写了一些东西,然后按 RETURN,那么集合将立即更新。
  • @Farzi,你能给我一个例子吗?

标签: c# wpf datagrid catel


【解决方案1】:

我看到您试图通过在您的 DataGridItemsSource 上使用 UpdateSourceTrigger=PropertyChanged 来解决您的问题。您想要的是更新单元格更改的单元格绑定源,而不是 DataGrid 项。

根据这种推理,很明显,在实例化 OnlineMarketerMixColumns 属性的 DataGridTextColumn 对象时需要调整绑定:

for (int i = 0; i < 4; i++)
{
    OnlineMarketerMixColumns.Add(
        new DataGridTextColumn
        {
            Header = string.Format("ColumnNumber"+i),
            Binding = new Binding(string.Format("[{0}]", i))
            {
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            },
        });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    相关资源
    最近更新 更多