【问题标题】:WPF - Binding FontFamily of TextBox to a ComboBoxWPF - 将 TextBox 的 FontFamily 绑定到 ComboBox
【发布时间】:2016-04-20 04:23:47
【问题描述】:

我知道这个帖子:TextBox FontFamily Binding,看起来类似于我的问题,但我的情况要简单得多,我想在 ComboBox 的值更改时将 TextBox 控件的 FontFamily 属性绑定到 ComboBox , TextBox 的内容会相应改变。我没有使用 VM 或依赖属性,我按照本教程进行操作:https://dotnetstories.wordpress.com/2011/07/31/using-type-converters-in-wpf/

并想出了:

<Window x:Class="NumericControlTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:NumericControlTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <local:FontFamilyConversions x:Key="FontFamilyConversions" />
</Window.Resources>

<DockPanel>

    <ComboBox  DockPanel.Dock="Top" x:Name="Fonttype" >
        <ComboBoxItem IsSelected="True">Arial</ComboBoxItem>
        <ComboBoxItem>Batang</ComboBoxItem>
        <ComboBoxItem>BatangChe</ComboBoxItem>
        <ComboBoxItem>Gungsuh</ComboBoxItem>
        <ComboBoxItem>GungsuhChe</ComboBoxItem>
        <ComboBoxItem>Courier New</ComboBoxItem>
    </ComboBox>
    <TextBox x:Name="editor" FontSize="16" FontFamily="{Binding Path=SelectedValue, ElementName=Fonttype, Mode=OneWay, Converter={StaticResource FontFamilyConversions}}" >

    </TextBox>
</DockPanel>

using System.Windows.Data;
using System.Windows.Media;

namespace NumericControlTest
{
    class FontFamilyConversions : IValueConverter
    {
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            FontFamily fontfamily = new FontFamily("Verdana");
            if (value != null)
            {
                fontfamily = new FontFamily(value.ToString());
            }
            return fontfamily;
        }

        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }
}

但它不起作用,在我更改 ComboBox 的值后,没有任何反应。

感谢您的宝贵时间。

【问题讨论】:

    标签: c# wpf data-binding


    【解决方案1】:

    return fontfamily; 上的断点将表明您没有从 value.ToString() 获得预期的结果。您需要从ComboBoxItem 获取Content

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        FontFamily fontfamily = new FontFamily("Verdana");
        ComboBoxItem selectedFont = value as ComboBoxItem;
        if (selectedFont != null)
        {
            fontfamily = new FontFamily(selectedFont.Content.ToString());
        }
        return fontfamily;
    }
    

    您可以通过将&lt;FontFamily&gt; 对象直接添加到ComboBox 来避免转换器:

    <ComboBox  DockPanel.Dock="Top" x:Name="Fonttype" SelectedIndex="0">
        <FontFamily>Arial</FontFamily>
        <FontFamily>Segoe UI</FontFamily>            
    </ComboBox>
    

    然后在没有转换器的情况下绑定到SelectedValue

    FontFamily="{Binding Path=SelectedValue, ElementName=Fonttype, Mode=OneWay}"
    

    或者您可能想自动获取已安装字体的列表:

    <ComboBox  DockPanel.Dock="Top" x:Name="Fonttype" ItemsSource="{x:Static Fonts.SystemFontFamilies}" SelectedIndex="0" />
    

    虽然SystemFontFamilies 不太可能被排序,所以你需要use a CollectionViewSource to sort

    【讨论】:

    • 真的很有趣,在我问这个问题之前,我实际上尝试输出表达式value.ToString(),我知道它是“System.Windows.Media.FontFamily: Arial”,但我也正如你所说,在返回 fontamily 上添加了一个断点,我发现它是正确的,正如预期的那样。不过,这有点奇怪。最重要的是您的建议有效,非常感谢。
    • @VincentZHANG 稍微扩展了答案
    • 这是一项很棒的工作,非常感谢。但是,将 添加为 直接子级超出了我的理解能力。那么,这意味着 在 XAML 中被识别为有效标签,对吧?当 XAML 被编译时,它会被转换成一个 FontFamily 对象吗?另一方面,我可以向 添加任何类吗?像 AliceBlue 然后将此 ComboBox 绑定到 TextBox 的 Foreground 属性。
    • @VincentZHANG 是的,你可以。根据对象,您可能需要指定 DataTemplate 以便它可以正确呈现。例如,对于颜色,您可能希望显示填充颜色的Rectangle 和带有颜色名称的TextBlock。模板设置在&lt;ComboBox.ItemTemplate&gt; 中,它也位于&lt;ComboBox&gt;..
    【解决方案2】:

    不必使用绑定转换器。

    相反,您可以将 FontFamily 分配给每个 ComboBoxItem 的 Tag 属性。这也可以让您对 ComboBox 项使用任意文本:

    <ComboBox x:Name="fontFamilyComboBox" SelectedValuePath="Tag">
        <ComboBoxItem Content="Arial">
            <ComboBoxItem.Tag>
                <FontFamily>Arial</FontFamily>
            </ComboBoxItem.Tag>
        </ComboBoxItem>
        <ComboBoxItem Content="Courier">
            <ComboBoxItem.Tag>
                <FontFamily>Courier New</FontFamily>
            </ComboBoxItem.Tag>
        </ComboBoxItem>
    </ComboBox>
    
    <TextBox Text="Hello, World."
             FontFamily="{Binding SelectedValue, ElementName=fontFamilyComboBox}"/>
    

    FontFamily 属性上的 SelectedValue 绑定直接返回 ComboBox 的 Tag 属性,因为在 ComboBox 上设置了 SelectedValuePath="Tag"。如果没有这个,FontFamily 绑定也可以这样写:

    <TextBox Text="Hello, World."
             FontFamily="{Binding SelectedItem.Tag, ElementName=fontFamilyComboBox}"/>
    

    【讨论】:

    • 谢谢你,Clemens,这种方法是否也适用于前景的
    • @VincentZHANG 除了你可以简单地尝试一下,是什么让你觉得它行不通?
    • 是的,好点,抱歉不清楚。我的问题是幕后的规则,有没有关于该机制的参考?
    • 不涉及特殊机制。您可以将任何内容放入 Tag 属性(对象类型)。因此,您可以在 XAML 中创建的任何内容都可以放入 XAML 中。如果您随后像FontFamily="{Binding SelectedItem.Tag ...} 那样绑定到 Tag 属性,则类型必须在运行时匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多