如何使 ComboBox 列的编辑器元素保存用户选择的新值?
How to make the ComboBox column's editor elements save the user-selected new value?
完整的 XAML 和代码隐藏如下。我有一个 Window 和一个带有单列的 DataGrid,一个 DataGridComboBoxColumn。在它的 EditingElementStyle 中,我将 ComboBox-es 设置为可编辑,并将它们的 ItemsSource 设置为我在 ElementStyle 属性 中绑定到的同一集合。在我 运行 程序并尝试将单元格的值更改为另一个值之前,绑定似乎运行良好。虽然我目前 select 仅来自现有值(将来我希望允许输入自定义项目),但该值不会保存,并且在移动焦点后会显示之前的值。
如果我把这个放在 Window:
<StackPanel Orientation="Vertical">
<ComboBox ItemsSource="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}" IsEditable="True"/>
<ComboBox ItemsSource="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}" IsEditable="True"/>
</StackPanel>
似乎一切正常。
XAML
<Window x:Class="cs_wpf_test_11.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:cs_wpf_test_11"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="TestWindow" Height="450" Width="800">
<Grid>
<DataGrid Name="MyDataGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="My only column"
SelectedItemBinding="{Binding Value, Mode=TwoWay}"
TextBinding="{Binding Value}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="IsEditable" Value="True"/>
<Setter Property="ItemsSource" Value="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
代码隐藏
public partial class TestWindow : Window
{
public ObservableCollection<ItemType> MyItems { get; set; }
public ObservableCollection<string> MyGroups { get; set; }
public TestWindow()
{
InitializeComponent();
MyGroups = new ObservableCollection<string>();
MyGroups.Add("test");
MyGroups.Add("test 2");
MyItems = new ObservableCollection<ItemType>();
MyItems.Add(new ItemType()
{
Value = "test"
});
MyItems.Add(new ItemType()
{
Value = "test 2"
});
MyDataGrid.ItemsSource = MyItems;
}
}
public class ItemType : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
protected string _Value = "";
public string Value
{
get
{
return _Value;
}
set
{
if (_Value != value)
{
_Value = value;
OnPropertyChanged("Value");
}
}
}
}
预期:
- 用户select是一个小区,
- 进入其编辑模式(通过双击或 F2)和
- selects 从下拉菜单中选择与之前显示的值不同的另一个值。
- 用户将 selected 单元格更改为另一个
- 并且先前获得焦点的单元格仍保留有新的 selected 值。
实际:用户执行与上述相同的步骤,但是在select输入新值后聚焦另一个单元格时,先前聚焦的单元格仍保持初始状态值。
看来 TextBinding
已经和 Mode=TwoWay
在一起了。我刚刚从标记中删除了这一行,一切都按预期工作:
SelectedItemBinding="{Binding Value, Mode=TwoWay}"
完整的 XAML 和代码隐藏如下。我有一个 Window 和一个带有单列的 DataGrid,一个 DataGridComboBoxColumn。在它的 EditingElementStyle 中,我将 ComboBox-es 设置为可编辑,并将它们的 ItemsSource 设置为我在 ElementStyle 属性 中绑定到的同一集合。在我 运行 程序并尝试将单元格的值更改为另一个值之前,绑定似乎运行良好。虽然我目前 select 仅来自现有值(将来我希望允许输入自定义项目),但该值不会保存,并且在移动焦点后会显示之前的值。
如果我把这个放在 Window:
<StackPanel Orientation="Vertical">
<ComboBox ItemsSource="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}" IsEditable="True"/>
<ComboBox ItemsSource="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}" IsEditable="True"/>
</StackPanel>
似乎一切正常。
XAML
<Window x:Class="cs_wpf_test_11.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:cs_wpf_test_11"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="TestWindow" Height="450" Width="800">
<Grid>
<DataGrid Name="MyDataGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="My only column"
SelectedItemBinding="{Binding Value, Mode=TwoWay}"
TextBinding="{Binding Value}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="IsEditable" Value="True"/>
<Setter Property="ItemsSource" Value="{Binding Path=MyGroups,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
代码隐藏
public partial class TestWindow : Window
{
public ObservableCollection<ItemType> MyItems { get; set; }
public ObservableCollection<string> MyGroups { get; set; }
public TestWindow()
{
InitializeComponent();
MyGroups = new ObservableCollection<string>();
MyGroups.Add("test");
MyGroups.Add("test 2");
MyItems = new ObservableCollection<ItemType>();
MyItems.Add(new ItemType()
{
Value = "test"
});
MyItems.Add(new ItemType()
{
Value = "test 2"
});
MyDataGrid.ItemsSource = MyItems;
}
}
public class ItemType : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
protected string _Value = "";
public string Value
{
get
{
return _Value;
}
set
{
if (_Value != value)
{
_Value = value;
OnPropertyChanged("Value");
}
}
}
}
预期:
- 用户select是一个小区,
- 进入其编辑模式(通过双击或 F2)和
- selects 从下拉菜单中选择与之前显示的值不同的另一个值。
- 用户将 selected 单元格更改为另一个
- 并且先前获得焦点的单元格仍保留有新的 selected 值。
实际:用户执行与上述相同的步骤,但是在select输入新值后聚焦另一个单元格时,先前聚焦的单元格仍保持初始状态值。
看来 TextBinding
已经和 Mode=TwoWay
在一起了。我刚刚从标记中删除了这一行,一切都按预期工作:
SelectedItemBinding="{Binding Value, Mode=TwoWay}"