Я нахожусь в ситуации, когда вопрос о том, очищается или нет данное ComboBox
в DataGridRow
, зависит от того, связан ли его ItemsSource
со строкой в DataGrid
или в родительском элементе.
Конкретно рассмотрим следующий WPF Window
:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (((ComboBox)sender).Items.Count == 0)
throw new InvalidOperationException("This seems unlikely!");
}
}
Тогда следующий пример работает, как я и ожидал; то есть, InvalidOperationException
в Selector_OnSelectionChanged
никогда не вызывается, что имеет смысл для меня, поскольку здесь нет ни одного пустого ComboBox
:
<Window x:Class="WpfApp1.MainWindow"
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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.Names, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"
SelectedItem="{Binding SelectedName}"
SelectionChanged="Selector_OnSelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public class ViewModel
{
public ViewModel()
{
Items = new List<Model>
{
new Model { SelectedName = "b" },
new Model { SelectedName = "a" }
};
}
public static List<string> Names { get; set; } = new List<string>
{
"a", "b"
};
public List<Model> Items { get; set; }
}
public class Model
{
public string SelectedName { get; set; }
}
Если теперь я переместлю список Names
в класс модели вместо этого (что в моем случае и будет тем, что я хочу, поскольку сама строка накладывает ограничения на содержимое ComboBox
) и обновлю Binding
соответственно, тогда я делаю ударил исключение, хотя, насколько я могу судить, задействованные ComboBox
такие же непустые, как в примере выше.
<Window x:Class="WpfApp1.MainWindow"
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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<!-- Binding below has changed -->
<ComboBox ItemsSource="{Binding Names}"
SelectedItem="{Binding SelectedName}"
SelectionChanged="Selector_OnSelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public class ViewModel
{
public ViewModel()
{
Items = new List<Model>
{
new Model { SelectedName = "b" },
new Model { SelectedName = "a" }
};
}
public List<Model> Items { get; set; }
// Names has been removed here
}
public class Model
{
public string SelectedName { get; set; }
// Names moved in here now instead
public static List<string> Names { get; set; } = new List<string>
{
"a", "b"
};
}
Все привязки работают одинаково, с той лишь разницей, что есть момент времени, когда ComboBox
пусто. Поэтому возникает вопрос: что является причиной этого, и есть ли способ избежать этого?