我制作了一个用户控件FontSelector,它将用于FontFamily Selection的ComboBox和用于粗体,斜体,下划线选项的三个ToggleButtons组合在一起。我遇到了ComboBox的SelectedItem属性的问题,该属性影响同一Window中该用户控件的所有实例。例如,在一个上更改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属性的值更新它的值。它有效地将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;
}
}
我想我可能已经知道发生了什么。我可以通过将ItemsSource绑定到以下集合视图源来复制它。
<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的作用。
答案 0 :(得分:1)
我让它有点不同。我将仅使用String而不是FontFamily或FontWeight来介绍此解决方案,因为我现在没有VS。 (为了让它工作,请将FontFamilies列表更改为绑定它们的字符串列表。)
您的选择器UserControl:
- 您的xaml
没问题(但您不会需要x:Name
)
- UserControl的CodeBehind(后来: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;}
- 在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 &#34;或类似的东西。
答案 1 :(得分:0)
发现问题。我绑定到Application Resources中定义的CollectionViewSource。到目前为止,我还没有意识到绑定到CollectionViewSource也会影响SelectedItem。 SelectedItem数据存储为CollectionViewSource的一部分。在ComboBox上将IsSynchronizedWithCurrentItem属性设置为False解决了这个问题。
这是我现在找到的existing answer。
由于