В моем приложении у меня есть DataGrid
, где пользователь может добавлять строки, нажимая Button
. При нажатии на кнопку новый экземпляр PlaceholderItem
будет добавлен к ObservableCollection<PlaceholderItem>
, к которому привязан DataGrid
.
Определение DataGrid
в представлении выглядит следующим образом:
<DataGrid ItemsSource="{Binding PlaceholderItems}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False"
Background="White" Grid.Row="1" MinHeight="70" MaxHeight="200" Margin="7,0" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Placeholder-Name" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox IsEditable="True" VerticalAlignment="Center" Margin="2"
ItemsSource="{Binding DataContext.AvailablePlaceholders, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
DisplayMemberPath="PlaceholderName"
Validation.ErrorTemplate="{StaticResource ComboBoxErrorTemplate}">
<ComboBox.Text>
<Binding Path="PlaceholderName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" >
<Binding.ValidationRules>
<local:PlaceholderValidationRule ValidationStep="UpdatedValue">
<local:PlaceholderValidationRule.PlaceholderValidationRuleParamData>
<local:PlaceholderValidationRuleParamData
UsedPlaceholders="{Binding Source={StaticResource proxy}, Path=Data.PlaceholderItems}"
AvailablePlaceholders="{Binding Source={StaticResource proxy}, Path=Data.AvailablePlaceholders}"/>
</local:PlaceholderValidationRule.PlaceholderValidationRuleParamData>
</local:PlaceholderValidationRule>
</Binding.ValidationRules>
</Binding>
</ComboBox.Text>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Placeholder-Value" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox VerticalAlignment="Center" Validation.ErrorTemplate="{StaticResource PlaceholderItemValueErrorTemplate}">
<TextBox.Text>
<Binding Path="PlaceholderValue" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<!--<Binding.ValidationRules>
<local:PlaceholderValueValidationRule/>
</Binding.ValidationRules>-->
</Binding>
</TextBox.Text>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Таким образом, ItemSource DataGrid
называется PlaceholderItems. Каждая строка DataGrid
состоит из двух столбцов. Первый столбец - ComboBox
, где можно выбрать имя PlaceholderItem
. А во втором столбце значение PlaceholderItem
Класс PlaceholderItem имеет только два строковых свойства, которые реализуют INotifyPropertyChanged.
ComboBox
в первом столбце каждой строки связан с ObservableCollection<PlaceholderItem>
. Таким образом, пользователь может выбрать элемент из ComboBox
, а значение PlaceholderItem
будет записано в TextBox
во втором столбце.
Для этого я использую следующий код в ViewModel:
public ObservableCollection<PlaceholderItem> PlaceholderItems
{
get
{
if (placeholderItems == null)
{
placeholderItems = new ObservableCollection<PlaceholderItem>();
placeholderItems.CollectionChanged += PlaceholderItemsOnCollectionChanged;
}
return placeholderItems;
}
}
private void PlaceholderItemsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (PlaceholderItem placeholderItem in e.NewItems.OfType<PlaceholderItem>())
{
placeholderItem.PropertyChanged += PlaceholderItemOnPropertyChanged;
}
}
if (e.OldItems != null)
{
foreach (PlaceholderItem placeholderItem in e.OldItems.OfType<PlaceholderItem>())
{
placeholderItem.PropertyChanged -= PlaceholderItemOnPropertyChanged;
}
}
}
private void PlaceholderItemOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "PlaceholderName")
{
PlaceholderItem targetAvailablePlaceholderItem =
AvailablePlaceholders.FirstOrDefault(p =>
p.PlaceholderName == ((PlaceholderItem)sender).PlaceholderName);
if (targetAvailablePlaceholderItem != null)
{
((PlaceholderItem)sender).PlaceholderValue = targetAvailablePlaceholderItem.PlaceholderValue;
}
}
}
Все просто отлично работает.
Проблема сейчас:
Если пользователь добавил новую строку и выбрал элемент из ComboBox
, я хочу удалить выбранный элемент из коллекции AvailablePlaceholder-Collection. Так что пользователь больше не может выбирать его в других строках.
Я пробовал следующее в PlaceholderItemOnProertyChanged-Method:
if (e.PropertyName == "PlaceholderName")
{
PlaceholderItem targetAvailablePlaceholderItem =
AvailablePlaceholders.FirstOrDefault(p =>
p.PlaceholderName == ((PlaceholderItem)sender).PlaceholderName);
if (targetAvailablePlaceholderItem != null)
{
((PlaceholderItem)sender).PlaceholderValue = targetAvailablePlaceholderItem.PlaceholderValue;
AvailablePlaceholders.Remove(targetAvailablePlaceholderItem);
}
((PlaceholderItem)sender).ForcePropertyChanged();
}
Элемент удален из коллекции, но значение в ComboBox
теперь пусто.
Есть ли возможность удалить элемент из ItemsSource ComboBox, но свойство Text ComboBox сохраняет значение?