用户控件子元素在多个实例之间共享值

本文关键字:实例 之间 共享 控件 元素 用户 | 更新日期: 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 解决了此问题。

这是我现在已经找到的现有答案。

谢谢