组合框选中的项目未更新
本文关键字:项目 更新 组合 | 更新日期: 2023-09-27 18:12:44
我正在使用一个组合框(WPF 4.0)来显示编辑器应用程序的用户定义的段落样式。这个组合框有两列:
(1)未格式化的段落名称
(2)文本"abcABC123",在第一列
这些是用户定义的段落样式类的公共属性(其中最后3个不是ResourceKeys,而是包含ResourceKeys的变量):
_NameInternal
_NameUI
_ResourceKey_background
_ResourceKey_foreground
_ResourceKey_fontFamily
问题:组合框显示一个SelectedItem。如果我打开一个对话框,更改SelectedItem的三个Binding属性中的一个或多个(背景,前景,字体family)和关闭对话框,则组合框的SelectedItem不更新。但如果我把它拉下来,它就会显示出来新的格式。
是否有办法解决这个问题在Xaml而不是c# ?
<Window.Resources>
<local2:_2StylesPara x:Key="_2stylesPara" />
<CollectionViewSource x:Key="_collectionViewSource_stylesPara" Source="{StaticResource _2stylesPara}">
<CollectionViewSource.SortDescriptions>
<!-- Requires 'xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
<scm:SortDescription PropertyName="_NameUI" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
<ComboBox Name="_cbStylesPara" HorizontalAlignment="Left"
ItemsSource="{Binding Source={StaticResource _collectionViewSource_stylesPara}}"
SelectedValuePath="_NameInternal" IsSynchronizedWithCurrentItem="True" >
<ComboBox.Resources>
<local2:_2ResourceLookupConverter x:Key="_resourceLookupConverter"/>
</ComboBox.Resources>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding _NameUI}" Grid.Column="0" VerticalAlignment="Center" />
<TextBlock Grid.Column="1" Text="abcABC123" Margin="3,0,0,0"
Background="{Binding _ResourceKey_background, Converter={StaticResource _resourceLookupConverter}}"
Foreground="{Binding _ResourceKey_foreground, Converter={StaticResource _resourceLookupConverter}}"
FontFamily="{Binding _ResourceKey_fontFamily, Converter={StaticResource _resourceLookupConverter}}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
背后代码:
public class _2ResourceLookupConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return App.Current.TryFindResource(value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
下面是用户定义的段落样式的两个类:
public class _2StylesPara : ObservableCollection<_2StylePara>
// ObservableCollection implements INotifyPropertyChanged
{
public _2StylesPara(){}
}
public class _2StylePara
{
public event PropertyChangedEventHandler PropertyChanged;
// This method is not reached if Background, Foreground or FontFamily changes
private void SetValue<T>(ref T property, T value, string propertyName = null)
{
if (object.Equals(property, value) == false)
{
property = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
private string _nameInternal = string.Empty;
private string _nameUI = string.Empty;
private string _resourceKey_background = string.Empty;
private string _resourceKey_foreground = string.Empty;
private string _resourceKey_fontFamily = string.Empty;
private string _resourceKey_nameUI = string.Empty;
private string _resourceKey_style = string.Empty;
private Style _style = null;
private ResourceDictionary _valuesRD = null;
private string _pathToValuesRD = string.Empty;
public string NameInternal
{
get { return this._nameInternal; }
set { SetValue(ref this._nameInternal, value); }
}
public string NameUI
{
get { return this._nameUI; }
set { SetValue(ref this._nameUI, value); }
}
public string ResourceKey_background
{
get { return this._resourceKey_background; }
set { SetValue(ref this._resourceKey_background, value); }
}
public string ResourceKey_foreground
{
get { return this._resourceKey_foreground; }
set { SetValue(ref this._resourceKey_foreground, value); }
}
public string ResourceKey_fontFamily
{
get { return this._resourceKey_fontFamily; }
set { SetValue(ref this._resourceKey_fontFamily, value); }
}
public string ResourceKey_nameUI
{
get { return this._resourceKey_nameUI; }
set { SetValue(ref this._resourceKey_nameUI, value); }
}
public string ResourceKey_style
{
get { return this._resourceKey_style; }
set { SetValue(ref this._resourceKey_style, value); }
}
public Style Style
{
get { return this._style; }
set { SetValue(ref this._style, value); }
}
public ResourceDictionary ValuesRD
{
get { return this._valuesRD; }
set { SetValue(ref this._valuesRD, value); }
}
public string PathToValuesRD
{
get { return this._pathToValuesRD; }
set { SetValue(ref this._pathToValuesRD, value); }
}
// Constructor
public _2StylePara(Style sty, string styleNameInternal, string styleNameUI, string resourceKey_style, string resourceKey_nameUI,
string resourceKey_foreground, string resourceKey_background, string resourceKey_fontFamily,
ResourceDictionary valuesRD, string pathToValuesRD)
{
_style = sty;
_nameInternal = styleNameInternal; // [ "_sty001" ]
_nameUI = styleNameUI; // [ "Standard" ]
_resourceKey_style = resourceKey_style; // [ "_stylePara001" ]
_resourceKey_nameUI = resourceKey_nameUI; // [ "_nameUi001 ]
_resourceKey_foreground = resourceKey_foreground; // [ "_brush_textcolor001" ]
_resourceKey_background = resourceKey_background; // [ "_brush_backcolor001" ]
_resourceKey_fontFamily = resourceKey_fontFamily; // [ "_fontFamily001" ]
_valuesRD = valuesRD; // This ResourceDictionary contains all style values
_pathToValuesRD = pathToValuesRD; // [ "...'Resources'1ParaStyleValuesRD001.xaml" ]
}
}
如果我理解正确的话,_ResourceKey_background和其他属性是用户定义的段落样式类的属性,包含在你的_2sytlesPara集合中。你所经历的行为是当你在后台改变这些属性时,视图没有更新。
在这种情况下,如果您更新您的模型(也就是UDF样式类实例之一),绑定应该收到有关更新的通知。它是由INotifyPropertyChanged完成的。PropertyChanged事件,该事件应该由模型触发。
绑定自动以另一种方式工作,因此当您更改视图上的某些内容时,您的模型会更新。
通知的标准属性模式是:class Model : INotifyPropertyChanged
{
private int _Name = default(int);
public int Name
{
get { return _Name; }
set
{
SetValue(ref this._Name, value);
}
}
private void SetValue<T>(ref T property, T value, [CallerMemberName]string propertyName = null)
{
if (object.Equals(property, value) == false)
{
property = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
我希望我理解你的问题,我可以帮助你。
更新:
IObservableCollection只通知绑定机制关于集合中的添加和删除。嵌套属性值的更改仍然不会自动反映
关于你的代码,我建议尝试以下修改:
首先,我不建议公共属性名以下划线开头。根据MS命名约定,以下划线开头的名称通常是私有的支持字段。
因此,修改相应的属性,如:private string _ResourceKey_nameUI = string.Empty;
public string ResourceKey_nameUI
{
get { return this._ResourceKey_nameUI; }
set { SetValue(ref this._ResourceKey_nameUI, value); }
}
还要更改属性的绑定:
<TextBlock Grid.Column="1" Text="abcABC123" Margin="3,0,0,0"
Background="{Binding ResourceKey_background, Converter={StaticResource _resourceLookupConverter}}"
Foreground="{Binding ResourceKey_foreground, Converter={StaticResource _resourceLookupConverter}}"
FontFamily="{Binding ResourceKey_fontFamily, Converter={StaticResource _resourceLookupConverter}}"/>
更新2
WPF绑定检查绑定的模型实例是否实现了INotifyPropertyChanged接口。请将您的类声明修改为:
public class _2StylePara : INotifyPropertyChanged
{
//...
}
此外,当您在后台更改值时,您应该使用属性而不是后台字段。当你改变NameUI SetValue功能会被调用,它会通知绑定刷新TextBlock。绑定也应该指向属性,而不是后面的字段。
因此:Text="{Binding NameUI}" NOT Text="{Binding _NameUI}"如果有帮助,请把答案标记为。谢谢。