[英]User Control Child elements sharing Value across multiple instances
我制作了一个用户控件FontSelector,它将用于FontFamily选择的ComboBox和用于粗体,斜体,下划线选项的三个ToggleButton组合在一起。 我在ComboBox的SelectedItem属性上遇到问题,影响了同一窗口内该用户控件的所有实例。 例如,更改其中一个的ComboBox选择将自动更改另一个。 为了清晰。 我不要这种行为。 我很惊讶用户控件暗中影响另一个用户控件。
<Grid x:Name="Grid" Background="White" DataContext="{Binding RelativeSource={RelativeSource AncestorType=local:FontSelector}}">
<ComboBox x:Name="comboBox" Width="135"
SelectedItem="{Binding Path=SelectedFontFamily}" Style="{StaticResource FontChooserComboBoxStyle}"
ItemsSource="{Binding Source={StaticResource SystemFontFamilies}}"/>
</Grid>
ComboBox的SelectedItem绑定到的CLR属性。 此处显示的代码位于文件后面的用户控制代码中,而不是ViewModel中。
private FontFamily _SelectedFontFamily;
public FontFamily SelectedFontFamily
{
get
{
return _SelectedFontFamily;
}
set
{
if (_SelectedFontFamily != value)
{
_SelectedFontFamily = value;
// Modify External Dependency Property Value.
if (value != SelectedFont.FontFamily)
{
SelectedFont = new Typeface(value, GetStyle(), GetWeight(), FontStretches.Normal);
}
// Notify.
RaisePropertyChanged(nameof(SelectedFontFamily));
}
}
}
根据ComboBox的SelectedItem属性的值更新其值的Dependency属性。 它有效地将FontFamily值打包到Typeface对象中。
public Typeface SelectedFont
{
get { return (Typeface)GetValue(SelectedFontProperty); }
set { SetValue(SelectedFontProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedFont. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedFontProperty =
DependencyProperty.Register("SelectedFont", typeof(Typeface), typeof(FontSelector),
new FrameworkPropertyMetadata(new Typeface("Arial"), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnSelectedFontPropertyChanged)));
private static void OnSelectedFontPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as FontSelector;
var newFont = e.NewValue as Typeface;
if (newFont != null)
{
instance.SelectedFontFamily = newFont.FontFamily;
}
}
我想我可能已经知道发生了什么事。 我可以通过将ItemsSource绑定到以下Collection View Source来复制它。
<CollectionViewSource x:Key="SystemFontFamilies" Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Source"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
然后,您可以通过放置2个ComboBox并将它们都绑定到CollectionViewSource来复制行为。 现在,它们似乎将隐式跟踪彼此的SelectedItem。 即使没有ItemsSource之外的任何数据绑定。 似乎CollectionViewSource在某种程度上参与了SelectedItem的作用。
我会有所不同。 我将仅使用String而不是FontFamily或FontWeight来介绍此解决方案,因为现在我这里没有VS。 (为了使其正常工作,请将FontFamilies的列表更改为绑定它们的字符串的列表。)
您的选择器UserControl:
-您的xaml
没问题(但是您不需要x:Name
)
-UserControl(之后为UC)的CodeBehind应该更改,我们将通过绑定解决它。 您应该有一个DependencyProperty
,让我们将其命名为SelectedFontFamily ,它将代表从ComboBox
选择的字符串:
public string SelectedFontFamily
{
get { return (string)GetValue(SelectedFontFamilyProperty); }
set { SetValue(SelectedFontFamilyProperty, value); }
}
public static readonly DependencyProperty SelectedFontFamilyProperty = DependencyProperty.Register("SelectedFontFamily", typeof(string), typeof(YourUC), new PropertyMetadata(string.Empty));
包含UC的窗口:
-您应该在窗口的开始标记中包含UC文件夹的名称空间,例如:
<Window
...
xmlns:view="clr-namespace:YourProjectName.Views.UserControls">
-窗口的DataContext应该具有带有public set选项的属性(可以在其上实现INotifyPropertyChange
):
public string FontFamily {get; set;}
-在Window的xaml中,您可以通过以下方式使用UC:
<view:YourUC SelectedFontFamily="{Binding FontFamily, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
这是双向绑定。 每次更改SelectedItem
都将找到选定的字符串作为FontFamily属性的值。
编辑:您将需要使用UserControl的Window的View Model类。 创建它,使其实现INotifyPropertyChanged
接口,并将其设置为使用者窗口的DataContext
。 WPF与WF不同,如果您通过Google注册“ WPF MVVM ”或类似的东西,可以找到更多有关WPF的信息 。
找到了问题。 我正在绑定到“应用程序资源”中定义的CollectionViewSource。 直到现在,我还没有意识到绑定到CollectionViewSource也将影响SelectedItem。 SelectedItem数据将作为CollectionViewSource的一部分存储。 将ComboBox上的IsSynchronizedWithCurrentItem属性设置为False可以解决此问题。
这是我现在找到的现有答案 。
谢谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.