WPF文本框会丢失原始值,即使用户没有';t更新

WPF文本框会丢失原始值,即使用户没有';t更新,wpf,binding,textbox,grid,mode,Wpf,Binding,Textbox,Grid,Mode,我有一个datagrid,它绑定到Person类型的可观察集合 所选项目将绑定到对象人员。 我有两个文本框firstname和lastname。 当任何一个用户从网格中选择一个项目时,文本框值都会被填充。 用户可以编辑值并单击提交按钮,值将得到更新 源到目标正常工作-即能够从viewModel显示 当我更新这些值时,它们会被更新 假设用户选择了名为john,姓为smith的项目 问题是用户将名字编辑为johnny,他没有单击submit按钮,而是从datagrid中选择了一个不同的项,所以当我返

我有一个datagrid,它绑定到Person类型的可观察集合 所选项目将绑定到对象人员。 我有两个文本框firstname和lastname。 当任何一个用户从网格中选择一个项目时,文本框值都会被填充。 用户可以编辑值并单击提交按钮,值将得到更新

源到目标正常工作-即能够从viewModel显示 当我更新这些值时,它们会被更新

假设用户选择了名为john,姓为smith的项目
问题是用户将名字编辑为johnny,他没有单击submit按钮,而是从datagrid中选择了一个不同的项,所以当我返回到原始选定项时。在网格中,所选项目显示为John smith,但在文本框中,值显示为Johnny smith

首先,将数据网格中的SelectedItem绑定到ObservableCollection中的一个项。然后将TextBox控件绑定到DataGrid中相同的SelectedItem(在我的示例中为SelectedCustomer)。然后通过实现INotifyPropertyChanged来更新SelectedCustomer,以使ObservableCollection与SelectedCustomer保持同步。 最后,如果需要,您可以在文本框控件中包含UpdateSourceTrigger=PropertyChanged,以在文本框中键入时更新数据网格

我已经包括了下面的代码(ViewModelBase除外)来帮助您开始

以下是带有DataGrid和两个TextBox控件的XAML:

<Window x:Class="DataGridTextBox.Views.MainView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:WpfToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
  Title="Main Window" Height="400" Width="800">
  <DockPanel>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <WpfToolkit:DataGrid  
            Grid.Column="0"
            SelectedItem="{Binding Path=SelectedCustomer, Mode=TwoWay}"
            ItemsSource="{Binding Path=Customers, Mode=OneWay}" >
        </WpfToolkit:DataGrid>
        <StackPanel Grid.Column="1">
            <TextBlock Text="First Name"/>
            <TextBox Text="{Binding Path=SelectedCustomer.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <TextBlock Text="Last Name"/>
            <TextBox Text="{Binding Path=SelectedCustomer.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </Grid>
  </DockPanel>
</Window>
最后是一个简单的客户定义:

public class Customer
{
  public String FirstName { get; set; }
  public String MiddleName { get; set; }
  public String LastName { get; set; }
  public String Address { get; set; }
  public Boolean IsNew { get; set; }

  // A null value for IsSubscribed can indicate 
  // "no preference" or "no response".
  public Boolean? IsSubscribed { get; set; }

  public Customer(String firstName, String lastName,
      String address, Boolean isNew, Boolean? isSubscribed)
  {
     this.FirstName = firstName;
     this.MiddleName = lastName;
     this.LastName = lastName;
     this.Address = address;
     this.IsNew = isNew;
     this.IsSubscribed = isSubscribed;
  }

  public static ObservableCollection<Customer> GetSampleCustomerList()
  {
     return new ObservableCollection<Customer>(new Customer[4] {
            new Customer("Jeff", "Zero", 
                "12 North Third Street, Apartment 45", 
                false, true), 
            new Customer("Joel", "One", 
                "34 West Fifth Street, Apartment 67", 
                false, false),
            new Customer("Jon", "Two", 
                "56 East Seventh Street, Apartment 89", 
                true, null),
            new Customer("Zamboni", "Three", 
                "78 South Ninth Street, Apartment 10", 
                true, true)
        });
  }
}
公共类客户
{
公共字符串名{get;set;}
公共字符串MiddleName{get;set;}
公共字符串LastName{get;set;}
公共字符串地址{get;set;}
公共布尔值IsNew{get;set;}
//IssuSubscribed的空值可能表示
//“无偏好”或“无响应”。
公共布尔值?已订阅{get;set;}
公共客户(字符串firstName、字符串lastName、,
字符串地址,布尔值isNew,布尔值isSubscribed)
{
this.FirstName=FirstName;
this.MiddleName=姓氏;
this.LastName=LastName;
这个地址=地址;
this.IsNew=IsNew;
this.IsSubscribed=IsSubscribed;
}
公共静态ObservableCollection GetSampleCustomerList()
{
返回新的ObservableCollection(新客户[4]{
新客户(“杰夫”,“零”,
“北三街12号,45号公寓”,
假,真),,
新客户(“Joel”,“One”,
“西五街34号,67号公寓”,
假,假),,
新客户(“乔恩”,“两个”,
“东七街56号,89号公寓”,
正确,无效),
新客户(“Zamboni”,“三”,
“南九街78号,10号公寓”,
真的,真的)
});
}
}

首先,将数据网格中的SelectedItem绑定到ObservableCollection中的一个项。然后将TextBox控件绑定到DataGrid中相同的SelectedItem(在我的示例中为SelectedCustomer)。然后通过实现INotifyPropertyChanged来更新SelectedCustomer,以使ObservableCollection与SelectedCustomer保持同步。 最后,如果需要,您可以在文本框控件中包含UpdateSourceTrigger=PropertyChanged,以在文本框中键入时更新数据网格

我已经包括了下面的代码(ViewModelBase除外)来帮助您开始

以下是带有DataGrid和两个TextBox控件的XAML:

<Window x:Class="DataGridTextBox.Views.MainView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:WpfToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
  Title="Main Window" Height="400" Width="800">
  <DockPanel>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <WpfToolkit:DataGrid  
            Grid.Column="0"
            SelectedItem="{Binding Path=SelectedCustomer, Mode=TwoWay}"
            ItemsSource="{Binding Path=Customers, Mode=OneWay}" >
        </WpfToolkit:DataGrid>
        <StackPanel Grid.Column="1">
            <TextBlock Text="First Name"/>
            <TextBox Text="{Binding Path=SelectedCustomer.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <TextBlock Text="Last Name"/>
            <TextBox Text="{Binding Path=SelectedCustomer.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </Grid>
  </DockPanel>
</Window>
最后是一个简单的客户定义:

public class Customer
{
  public String FirstName { get; set; }
  public String MiddleName { get; set; }
  public String LastName { get; set; }
  public String Address { get; set; }
  public Boolean IsNew { get; set; }

  // A null value for IsSubscribed can indicate 
  // "no preference" or "no response".
  public Boolean? IsSubscribed { get; set; }

  public Customer(String firstName, String lastName,
      String address, Boolean isNew, Boolean? isSubscribed)
  {
     this.FirstName = firstName;
     this.MiddleName = lastName;
     this.LastName = lastName;
     this.Address = address;
     this.IsNew = isNew;
     this.IsSubscribed = isSubscribed;
  }

  public static ObservableCollection<Customer> GetSampleCustomerList()
  {
     return new ObservableCollection<Customer>(new Customer[4] {
            new Customer("Jeff", "Zero", 
                "12 North Third Street, Apartment 45", 
                false, true), 
            new Customer("Joel", "One", 
                "34 West Fifth Street, Apartment 67", 
                false, false),
            new Customer("Jon", "Two", 
                "56 East Seventh Street, Apartment 89", 
                true, null),
            new Customer("Zamboni", "Three", 
                "78 South Ninth Street, Apartment 10", 
                true, true)
        });
  }
}
公共类客户
{
公共字符串名{get;set;}
公共字符串MiddleName{get;set;}
公共字符串LastName{get;set;}
公共字符串地址{get;set;}
公共布尔值IsNew{get;set;}
//IssuSubscribed的空值可能表示
//“无偏好”或“无响应”。
公共布尔值?已订阅{get;set;}
公共客户(字符串firstName、字符串lastName、,
字符串地址,布尔值isNew,布尔值isSubscribed)
{
this.FirstName=FirstName;
this.MiddleName=姓氏;
this.LastName=LastName;
这个地址=地址;
this.IsNew=IsNew;
this.IsSubscribed=IsSubscribed;
}
公共静态ObservableCollection GetSampleCustomerList()
{
返回新的ObservableCollection(新客户[4]{
新客户(“杰夫”,“零”,
“北三街12号,45号公寓”,
假,真),,
新客户(“Joel”,“One”,
“西五街34号,67号公寓”,
假,假),,
新客户(“乔恩”,“两个”,
“东七街56号,89号公寓”,
正确,无效),
新客户(“Zamboni”,“三”,
“南九街78号,10号公寓”,
真的,真的)
});
}
}

谢谢大家。该问题通过取消激活事件解决。因此,每当用户单击网格中的新项目时,旧项目取消激活事件将检查数据是否已从原始项目更改。如果是,它将显示一条警告消息,供用户选择新项目或保留并完成编辑。如果用户希望返回并完成编辑,则使用e.Cancel=true取消事件;活动记录保留在旧项目中。如果用户继续进行新选择,旧值将恢复到对象


我相信可能会有更好的解决办法,而且我绝对愿意学习。非常感谢你的努力。非常感谢。

谢谢大家。该问题通过取消激活事件解决。因此,每当用户单击网格中的新项目时,旧项目取消激活事件将检查数据是否已从原始项目更改。如果是,它将显示一条警告消息,供用户选择新项目或保留并完成编辑。如果用户希望返回并完成编辑,则e