重新加载 ItemsSource 时 WPF UserControl 组合框绑定选择丢失
WPF UserControl Combobox Bound Selection Lost when ItemsSource reloaded
我有一个显示 ComboBox 以及添加和编辑按钮的 UserControl。
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;
}
}
在一个表单上多次使用维护框,以从共享的业务联系人列表中为不同的业务角色进行选择。所有使用用户控件的用户都可以添加或编辑一个条目。发生这种情况时,将刷新数据以允许选择。
维护组合框控件的使用
<utilctl:MaintenanceComboBox x:Name="cboFieldService" DisplayItem="FullName" DisplayRecordKey="ActorID"
ModelPropertyField="{Binding FieldServiceRep, Mode=TwoWay}"
DataSource="{Binding ContactList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
在记录的初始显示时,一切都按预期运行:
- 联系人列表加载到所有维护箱控件中
- 当前的业务角色选择显示为所选项目。
添加或编辑记录过程完成并刷新数据后,当前选择的项目丢失,而下拉列表显示更新的联系人列表。
视图模型是提供维护控件并实现 INotify属性Changed 的表单的 DataContext。表单相当大,并且是非常重复的功能。
属性 cboFieldService 的定义
private string _fieldServiceRep = string.Empty;
public string FieldServiceRep { get { return _fieldServiceRep; } set { _fieldServiceRep = value; OnPropertyChanged(); } }
在过去几天对此进行研究时,有很多人提到:
- INotify属性已更改 - 正在实施
- 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));
}
更新#2 ------
根据建议,重新定义了数据源并删除了对 属性ChangedCallback 的引用。结果是行为没有改变。
该行为仅在 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>)));
前像
联系人信息更新后的图片(Mode=TwoWay)
您可以不使用 object
作为数据源 属性,而是使用 ObservableCollection
吗?然后,不是重新加载 DataSourceChanged 方法中的项目,而是将其上的任何 add/remove 操作自动传递给具有数据绑定的 XAML。
ContactList = new ObservableCollection<ActorModel>(actors);
这行可能是问题所在,因为您要在此处创建新列表,而您可以向现有 OvservableCollection 添加或添加范围。
创建一个新实例将refresh your whole collection
(这就是你在那里所做的,因为你失去了选择)。
您的目标是添加或删除项目。没有刷新整个集合。
检查 this。希望这样你不会因为刷新而丢失你的选择。
原来是使用TemplateBinding的时候出了问题。对用户控件和 DependecyProperty 定义进行了以下更新。给原来的 post 记下无法花时间解释原因的讨厌者....继续走。
归功于 Microsoft forum post.
上的 TSoftware-Old
<ComboBox x:Name="cboMaintenance" Grid.Column="0" Grid.Row="1"
Background="{StaticResource BH_TitleDefaultBackground}" Foreground="Black"
VerticalContentAlignment="Center"
ItemsSource="{Binding DataSource, RelativeSource={RelativeSource TemplatedParent}}"
DisplayMemberPath="{Binding DisplayItem, RelativeSource={RelativeSource TemplatedParent}}"
SelectedValue="{Binding ModelPropertyField, RelativeSource={RelativeSource TemplatedParent}}"
SelectedValuePath="{Binding DisplayRecordKey, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding ModelSelectionItem, RelativeSource={RelativeSource TemplatedParent}}"/>
-------------------------
public static readonly DependencyProperty ModelSelectionItemProperty =
DependencyProperty.Register("ModelSelectionItem", typeof(object), typeof(MaintenanceComboBox),
new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
我有一个显示 ComboBox 以及添加和编辑按钮的 UserControl。
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;
}
}
在一个表单上多次使用维护框,以从共享的业务联系人列表中为不同的业务角色进行选择。所有使用用户控件的用户都可以添加或编辑一个条目。发生这种情况时,将刷新数据以允许选择。
维护组合框控件的使用
<utilctl:MaintenanceComboBox x:Name="cboFieldService" DisplayItem="FullName" DisplayRecordKey="ActorID"
ModelPropertyField="{Binding FieldServiceRep, Mode=TwoWay}"
DataSource="{Binding ContactList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
在记录的初始显示时,一切都按预期运行:
- 联系人列表加载到所有维护箱控件中
- 当前的业务角色选择显示为所选项目。
添加或编辑记录过程完成并刷新数据后,当前选择的项目丢失,而下拉列表显示更新的联系人列表。
视图模型是提供维护控件并实现 INotify属性Changed 的表单的 DataContext。表单相当大,并且是非常重复的功能。
属性 cboFieldService 的定义
private string _fieldServiceRep = string.Empty;
public string FieldServiceRep { get { return _fieldServiceRep; } set { _fieldServiceRep = value; OnPropertyChanged(); } }
在过去几天对此进行研究时,有很多人提到:
- INotify属性已更改 - 正在实施
- 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));
}
更新#2 ------
根据建议,重新定义了数据源并删除了对 属性ChangedCallback 的引用。结果是行为没有改变。
该行为仅在 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>)));
前像
联系人信息更新后的图片(Mode=TwoWay)
您可以不使用 object
作为数据源 属性,而是使用 ObservableCollection
吗?然后,不是重新加载 DataSourceChanged 方法中的项目,而是将其上的任何 add/remove 操作自动传递给具有数据绑定的 XAML。
ContactList = new ObservableCollection<ActorModel>(actors);
这行可能是问题所在,因为您要在此处创建新列表,而您可以向现有 OvservableCollection 添加或添加范围。
创建一个新实例将refresh your whole collection
(这就是你在那里所做的,因为你失去了选择)。
您的目标是添加或删除项目。没有刷新整个集合。
检查 this。希望这样你不会因为刷新而丢失你的选择。
原来是使用TemplateBinding的时候出了问题。对用户控件和 DependecyProperty 定义进行了以下更新。给原来的 post 记下无法花时间解释原因的讨厌者....继续走。
归功于 Microsoft forum post.
上的 TSoftware-Old<ComboBox x:Name="cboMaintenance" Grid.Column="0" Grid.Row="1"
Background="{StaticResource BH_TitleDefaultBackground}" Foreground="Black"
VerticalContentAlignment="Center"
ItemsSource="{Binding DataSource, RelativeSource={RelativeSource TemplatedParent}}"
DisplayMemberPath="{Binding DisplayItem, RelativeSource={RelativeSource TemplatedParent}}"
SelectedValue="{Binding ModelPropertyField, RelativeSource={RelativeSource TemplatedParent}}"
SelectedValuePath="{Binding DisplayRecordKey, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding ModelSelectionItem, RelativeSource={RelativeSource TemplatedParent}}"/>
-------------------------
public static readonly DependencyProperty ModelSelectionItemProperty =
DependencyProperty.Register("ModelSelectionItem", typeof(object), typeof(MaintenanceComboBox),
new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });