用户控件子元素在多个实例之间共享值
本文关键字:实例 之间 共享 控件 元素 用户 | 更新日期: 2023-09-27 18:32:02
我制作了一个用户控件FontSelector,它将一个用于FontFamily Selection的组合框和三个用于粗体,斜体,下划线选项的切换按钮组合在一起。组合框的 SelectedItem 属性影响同一窗口中该用户控件的所有实例时遇到问题。例如,更改其中一个的组合框选择将自动更改另一个。为了清楚起见。我不希望这种行为。我非常惊讶一个用户控件隐式影响另一个用户控件。
XAML
<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>
代码隐藏
组合框的选定项绑定到的 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));
}
}
}
依赖项属性,它根据组合框的选定项属性的值更新其值。它有效地将 FontFamily 值打包到字体对象中。
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;
}
}
编辑
我想我可能已经弄清楚发生了什么。我可以通过将项目源绑定到以下集合视图源来复制它。
<CollectionViewSource x:Key="SystemFontFamilies" Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Source"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
然后,可以通过放置 2 个组合框并将它们都绑定到 CollectionViewSource 来复制行为。他们现在将隐含地跟踪彼此的选定项。即使没有任何项目源之外的数据绑定。似乎CollectionViewSource以某种方式在SelectedItem中发挥了作用。
我会让它有点不同。我将仅使用String而不是FontFamily或FontWeight来介绍此解决方案,因为我现在这里没有VS。(为了使它正常工作,请将字体系列列表更改为字符串列表以绑定它们。
您的选择器用户控件:
- 你的xaml
没问题(但你不需要x:Name
)
- 用户控件(后来:UC)的代码隐藏应该改变,我们将通过绑定来解决它。你应该有一个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 应该有一个带有公共设置选项的属性(随意在其上实现INotifyPropertyChange
):
public string FontFamily {get; set;}
- 在窗口的 xaml 中,您将以这种方式使用 UC:
<view:YourUC SelectedFontFamily="{Binding FontFamily, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
这是一个双向绑定。每次更改SelectedItem
时,您都会发现所选字符串作为 FontFamily 属性的值。
编辑:您将需要使用用户控件的窗口的视图模型类。创建它,使其实现INotifyPropertyChanged
接口,并将其设置为使用者窗口的DataContext
。WPF 不像 WF,如果你在谷歌上搜索"WPF MVVM"或类似的东西,你可以找到更多关于它的信息。
发现问题。我绑定到应用程序资源中定义的 CollectionViewSource。直到现在,我还不知道绑定到 CollectionViewSource 也会影响 SelectedItem。选定项数据将存储为 CollectionViewSource 的一部分。在组合框上将 IsSyncdWithCurrentItem 属性设置为 False 解决了此问题。
这是我现在已经找到的现有答案。
谢谢