0

在我的程序中,我有一个DataGrid是 UserControl 的一部分。我希望能够更改此网格中单元格的值,并将它们存储在数据模型中。这类似于标准数据绑定textBox在 wpf 中的工作方式。

由esDataGrid组成。TextBox我可以更改单元格中的值,但它们在离开页面后消失。

用户控件 XAML:

<DataGrid ItemsSource="{Binding DataModel.Collection}" ... >
              <DataGrid.Columns>
                   <DataGridTemplateColumn IsReadOnly="True">
                         <DataGridTemplateColumn.CellTemplate>
                               <DataTemplate>
                                    <TextBox Text="{Binding rowNum}" />
                                </DataTemplate>
                         </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                          .......
                    </DataGrid>

数据模型:

public class Data_Model : PropertyChangedBase
{
    private string one = "One";
    private string two = "Two";
    private string three = "Three";
    private string four = "Four";
    private string a = "A";
    private string b = "B";
    private string c = "C";
    private string d = "D";

    private ObservableCollection<Class> _Collection; 

    public Data_Model()
    {
        Collection = new ObservableCollection<Class>();
        Collection.Add(new Class() { rowNum = 0, input = one, output = a });
        Collection.Add(new Class() { rowNum = 1, input = two, output = b});
        Collection.Add(new Class() { rowNum = 2, input = three, output = c});
        Collection.Add(new Class() { rowNum = 3, input = four, output = d});

    }

    public ObservableCollection<Class> Collection {...}
}

public class Class //Class for DataGrid values
{
    public int rowNum { set; get; }
    public string input { set; get; }
    public string output { set; get; }
}

如何像通常那样将用户输入的值存储在这些单元格中(通过编写一个属性string作为 中的文本textBox)?

4

2 回答 2

1

当单元格可编辑时,WPF DataGrid 使用事务范围。这意味着 DataGrid 正在发布您的视图模型目前未在听的“提交”和“取消”命令。这就是为什么更改似乎不会持续存在的原因(即,您忽略了这些实例上的“提交”)。

为了捕获“提交”和“取消”消息,绑定的类应该实现 IEditableObject 并编写必要的逻辑。IEditableObject 上的文档在这里:http: //msdn.microsoft.com/en-us/library/system.componentmodel.ieditableobject.aspx

当在ROW上完成“取消”时,网格会回滚在该行的CELLS上完成的所有提交。WPF DataGrid 的这一方面已经吸引了很多人,因此它获得了“陷阱”的地位......

如果您不熟悉 IEditableObject,请参阅这篇 MSDN 文章,其中有很好的解释和代码示例。DataGrid 具有通过 IEditableObject 接口进行事务编辑的功能。当您开始编辑单元格时,DataGrid 会进入单元格编辑模式和行编辑模式。这意味着您可以取消/提交单元格以及取消/提交行。例如,我编辑单元格 0 并按 Tab 键转到下一个单元格。按 T​​ab 键时提交单元格 0。我开始在单元格 1 中输入并意识到我想取消操作。我按“Esc”,它会恢复单元格 1。我现在意识到我想取消整个操作,所以我再次按“Esc”,现在单元格 0 恢复到其原始值。

资料来源:http: //blogs.msdn.com/b/vinsibal/archive/2009/04/07/5-random-gotchas-with-the-wpf-datagrid.aspx

因此,在“类”类上实现 IEditableObject,您将开始获得您正在寻找的行为。完成后应该是这样的......

public class Class : INotifyPropertyChanged, IEditableObject
{
    private int _rowNum;
    public int RowNum
    {
        [DebuggerStepThrough]
        get { return _rowNum; }
        [DebuggerStepThrough]
        set
        {
            if (value != _rowNum)
            {
                _rowNum = value;
                OnPropertyChanged("RowNum");
            }
        }
    }
    private string _input;
    public string Input
    {
        [DebuggerStepThrough]
        get { return _input; }
        [DebuggerStepThrough]
        set
        {
            if (value != _input)
            {
                _input = value;
                OnPropertyChanged("Input");
            }
        }
    }
    private string _output;
    public string Output
    {
        [DebuggerStepThrough]
        get { return _output; }
        [DebuggerStepThrough]
        set
        {
            if (value != _output)
            {
                _output = value;
                OnPropertyChanged("Output");
            }
        }
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
    #region IEditableObject Implementationi
    public void BeginEdit()
    {
        // your implementation goes here
    }
    public void CancelEdit()
    {
        // your implementation goes here
    }
    public void EndEdit()
    {
        // your implementation goes here
    }
    #endregion
}
于 2013-10-22T20:41:49.240 回答
1

我相信您只需要为 data_model 中的每个属性调用 NotifyPropertyChanged("PropertyName") 并设置绑定Mode=twoway

private int rowNum;

public int RowNum
{
    get { return rowNum; }
    set
    {
        rowNum = value;
        RaisePropertyChanged("RowNum");
    }
}

此外,您可以尝试 DataGridTextColumn 而不是 templatecolumn 如下

<Window.Resources>
    <XmlDataProvider x:Key="customerdata" Source="customers.xml" XPath="Data" />
</Window.Resources>
<Grid>
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Source={StaticResource customerdata}, XPath=Customer}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="First Name" Binding="{Binding XPath=@FirstName}" FontFamily="Arial" FontStyle="Italic" />
            <DataGridTextColumn Header="Last Name" Binding="{Binding XPath=@LastName}" FontFamily="Arial" FontWeight="Bold" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>
于 2013-10-22T20:57:17.040 回答