У меня есть UserControl, который отображает ComboBox вместе с кнопками добавления и редактирования.
Блок кода XAML
<Style TargetType="local:MaintenanceComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MaintenanceComboBox">
<Border x:Name="_boxBorder">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="cboMaintenance" Grid.Column="0"
Background="{StaticResource BH_TitleDefaultBackground}" Foreground="Black"
VerticalContentAlignment="Center"
ItemsSource="{TemplateBinding DataSource}"
DisplayMemberPath="{TemplateBinding DisplayItem}"
SelectedValue="{TemplateBinding ModelPropertyField}"
SelectedValuePath="{TemplateBinding DisplayRecordKey}"/>
<Button Grid.Column="1" Name="btnAddRecord" ToolTip="Add Record" Style="{StaticResource IconButton}" Margin="1.5,0" Background="Transparent"
Command="{TemplateBinding AddRecordCommand}">
<Image Source="{Binding Converter={StaticResource ImgConverter}, ConverterParameter={x:Static utilui:eImages_16x16.Add} }"/>
</Button>
<Button Grid.Column="2" Name="btnEditRecord" ToolTip="Edit Record" Margin="1.5,0" Background="Transparent"
Command="{TemplateBinding EditRecordCommand}">
<Image Source="{Binding Converter={StaticResource ImgConverter}, ConverterParameter={x:Static utilui:eImages_16x16.PageEdit} }"/>
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource IconButton}" >
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cboMaintenance, Path=SelectedIndex}" Value="0">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Код управления содержимым
public class MaintenanceComboBox : ContentControl
{
private static object _previousSelection = null;
public ICommand AddRecordCommand
{
get { return (ICommand)GetValue(AddRecordCommandProperty); }
set { SetValue(AddRecordCommandProperty, value); }
}
public static readonly DependencyProperty AddRecordCommandProperty =
DependencyProperty.Register("AddRecordCommand", typeof(ICommand), typeof(MaintenanceComboBox),
new PropertyMetadata(default(ICommand), new PropertyChangedCallback(AddRecordCommandChanged)));
private static void AddRecordCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).AddRecordCommand = (ICommand)e.NewValue;
}
public ICommand EditRecordCommand
{
get { return (ICommand)GetValue(EditRecordCommandProperty); }
set { SetValue(EditRecordCommandProperty, value); }
}
public static readonly DependencyProperty EditRecordCommandProperty =
DependencyProperty.Register("EditRecordCommand", typeof(ICommand), typeof(MaintenanceComboBox),
new PropertyMetadata(default(ICommand), new PropertyChangedCallback(EditRecordCommandChanged)));
private static void EditRecordCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).EditRecordCommand = (ICommand)e.NewValue;
}
//------------------------------------------------------------------------------------------
public Color BackgroundColor
{
get { return (Color)GetValue(BackgroundColorProperty); }
set { SetValue(BackgroundColorProperty, value); }
}
public static readonly DependencyProperty BackgroundColorProperty =
DependencyProperty.Register("BackgroundColor", typeof(Color), typeof(MaintenanceComboBox),
new PropertyMetadata(default(Color), new PropertyChangedCallback(BackgroundColorChanged)));
private static void BackgroundColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).BackgroundColor = (Color)e.NewValue;
}
//------------------------------------------------------------------------------------------
public object DataSource
{
get { return GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource", typeof(object), typeof(MaintenanceComboBox),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, DataSourceChanged));
private static void DataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).DataSource = e.NewValue;
}
//------------------------------------------------------------------------------------------
public string DisplayItem
{
get { return GetValue(DisplayItemProperty).ToString(); }
set { SetValue(DisplayItemProperty, value); }
}
public static readonly DependencyProperty DisplayItemProperty =
DependencyProperty.Register("DisplayItem", typeof(string), typeof(MaintenanceComboBox),
new PropertyMetadata(default(string), new PropertyChangedCallback(DisplayItemChanged)));
private static void DisplayItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).DisplayItem = e.NewValue.ToString();
}
//------------------------------------------------------------------------------------------
public string DisplayRecordKey
{
get { return GetValue(DisplayRecordKeyProperty).ToString(); }
set { SetValue(DisplayRecordKeyProperty, value); }
}
public static readonly DependencyProperty DisplayRecordKeyProperty =
DependencyProperty.Register("DisplayRecordKey", typeof(string), typeof(MaintenanceComboBox),
new PropertyMetadata(default(string), new PropertyChangedCallback(DisplayRecordKeyChanged)));
private static void DisplayRecordKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).DisplayRecordKey = e.NewValue.ToString();
}
//------------------------------------------------------------------------------------------
public object ModelPropertyField
{
get { return GetValue(ModelPropertyFieldProperty); }
set { SetValue(ModelPropertyFieldProperty, value); }
}
public static readonly DependencyProperty ModelPropertyFieldProperty =
DependencyProperty.Register("ModelPropertyField", typeof(object), typeof(MaintenanceComboBox),
new PropertyMetadata(default(object), new PropertyChangedCallback(ModelPropertyFieldChanged)));
private static void ModelPropertyFieldChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).ModelPropertyField = e.NewValue;
}
//------------------------------------------------------------------------------------------
public int SelectedIndex
{
get { return Convert.ToInt32(GetValue(SelectedIndexProperty)); }
set { SetValue(SelectedIndexProperty, value); }
}
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(MaintenanceComboBox),
new PropertyMetadata(default(int), new PropertyChangedCallback(SelectedIndexChanged)));
private static void SelectedIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).SelectedIndex = Convert.ToInt32(e.NewValue);
}
//------------------------------------------------------------------------------------------
public object ModelSelectionItem
{
get { return GetValue(ModelSelectionItemProperty); }
set { SetValue(ModelSelectionItemProperty, value); }
}
public static readonly DependencyProperty ModelSelectionItemProperty =
DependencyProperty.Register("ModelSelectionItem", typeof(object), typeof(MaintenanceComboBox),
new PropertyMetadata(default(object), new PropertyChangedCallback(ModelSelectionItemChanged)));
private static void ModelSelectionItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MaintenanceComboBox)d).ModelSelectionItem = e.NewValue;
}
}
Блок обслуживания используется несколько раз приФорма для выбора из общего списка деловых контактов для отдельных бизнес-ролей.Все виды использования пользовательского элемента управления могут добавлять или редактировать запись.Когда это произойдет, данные будут обновлены для обеспечения возможности выбора.
Использование элемента управления ComboBox для обслуживания
<utilctl:MaintenanceComboBox x:Name="cboFieldService" DisplayItem="FullName" DisplayRecordKey="ActorID"
ModelPropertyField="{Binding FieldServiceRep, Mode=TwoWay}"
DataSource="{Binding ContactList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
При первоначальном отображении записивсе работает как положено:
- список контактов загружен во все элементы управления окна обслуживания
- текущие выбранные бизнес-роли отображаются как выбранный элемент.
После завершения процесса добавления или редактирования записи и обновления данных выбранный элемент теряется, а в раскрывающемся списке отображается обновленный список контактов.
Модель представления - это DataContext для формы, которая передает элементы управления обслуживанием и реализует INotifyPropertyChanged.Форма довольно большая и имеет довольно повторяющиеся функциональные возможности.
Определение свойства для cboFieldService
private string _fieldServiceRep = string.Empty;
public string FieldServiceRep { get { return _fieldServiceRep; } set { _fieldServiceRep = value; OnPropertyChanged(); } }
При исследовании этого в последние несколько дней было много упоминанийto:
- INotifyPropertyChanged - реализуется
- IsSyncronizeWithCurrentItem - не может быть установлено в значение true, поскольку использование пользовательского элемента управлениявсе независимые выборки, которые совместно используют один и тот же пул выбора контактов
Отладка за последние несколько дней указывает на то, что значения свойств отдельных выборок контактов остаются неизменными, однако они не отображаются после обновления.Что можно сделать, чтобы каждый выбранный список правильно отображался после обновления списка контактов после добавления или редактирования?
ОБНОВЛЕНИЕ № 1 ------
Когда запись загружена, команды добавления и редактирования определяются в модели представления.
public void LoadRecord(IncidentModel record)
{
DataContext = _activeIncident;
cboFieldService.AddRecordCommand = new DelegateCommand(_activeIncident.AddFieldServiceRep);
cboFieldService.EditRecordCommand = new DelegateCommand(_activeIncident.EditFieldServiceRep);
}
public void AddFieldServiceRep() { AddContact(nameof(FieldServiceRep)); }
public void AddContact(string propertyName)
{
ProcessContactMaintenance(new ContactMaintenanceWindow(MaintenanceType.Add), propertyName);
}
public void EditFieldServiceRep() { EditContact(ContactTypeCode.Rep, nameof(FieldServiceRep)); }
public void EditContact(ContactTypeCode type, string propertyName)
{
ProcessContactMaintenance(new ContactMaintenanceWindow(MaintenanceType.Edit, GetIncidentContact(type)?.ActorInfo), propertyName);
}
private void ProcessContactMaintenance(ContactMaintenanceWindow win, string propertyName)
{
win.ShowDialog();
if (win.DialogResult.Equals(true))
{
RefreshContactList(); OnPropertyChanged(nameof(ContactList)); UpdateContactProperties();
}
}
public void RefreshContactList()
{
ObservableCollection<ActorModel> contacts = new ObservableCollection<ActorModel>(FieldServiceManagementDataService.GetActors());
List<ActorModel> actors = contacts?.OrderBy(c => c.FullName).ToList();
ActorModel none = new ActorModel();
none.ActorID = "-1";
none.FirstName = "-- Select --";
actors?.Insert(0, none);
ContactList = new ObservableCollection<ActorModel>(actors);
}
public void UpdateContactProperties()
{
OnPropertyChanged(nameof(FieldServiceRep));
}
UPDATE # 2 ------
В соответствии с рекомендацией источник данных был переопределен, а ссылка на PropertyChangedCallback удалена.Результатом было неизменное поведение.
Поведение возникает только тогда, когда режим привязки ContactList = TwoWay.Когда он установлен в OneWay, выбор ComboBox не отображает обновленной информации, а выбор записей отображается визуально.
public ObservableCollection<dynamic> DataSource
{
get { return (ObservableCollection<dynamic>)GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource", typeof(ObservableCollection<dynamic>), typeof(MaintenanceComboBox),
new PropertyMetadata(default(ObservableCollection<dynamic>)));
Перед изображением
Изображение после обновления контактной информации (Режим = Двухсторонний)