这是一个错误吗?在运行时在Windows应用商店应用的代码中更改TextBlock样式

时间:2013-01-02 17:50:52

标签: xaml microsoft-metro windows-runtime

对我来说,从SO开始到新的一年:)

我正在尝试用我认为简单的事情来帮助朋友。基本上我们只想在代码中更改运行时的样式并更新TextBlock的样式。

除了TextBlock之外,我没有任何问题可以使用任何其他类型的元素。如果我在这里错过了一些东西,或者确实存在错误,我现在非常好奇。解决这个问题最好的方法是什么?

此处的代码仅用于演示,它适用于TextBox但不适用于TextBlock(当然,当targettype等更改时)

在Commondictionary中定义的名为StandardStyles的资源中定义的样式

    <Style x:Key="textStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="red"/>
    <Setter Property="FontFamily" Value="Segoe UI"/>
</Style>

用户界面

    <StackPanel Orientation="Horizontal">
    <ListBox ItemsSource="{Binding Fonts}" Height="300" Width="300" SelectionChanged="ListBox_SelectionChanged_1"></ListBox>
    <Border BorderBrush="White" BorderThickness="5" Padding="20,0,0,0" Height="300" Width="300">
        <TextBlock Text="Hi here is some text" Style="{Binding FontStyleText}"/>
    </Border>
</StackPanel>

代码

    public sealed partial class MainPage : INotifyPropertyChanged 
{
    private Style _fontStyleText;
    public Style FontStyleText
    {
        get
        {
            return this._fontStyleText;
        }

        set
        {
            if (value == this._fontStyleText) return;
            this._fontStyleText = value;
            NotifyPropertyChanged();
        }
    }

    private List<string> _fonts;
    public List<string> Fonts
    {
        get
        {
            return this._fonts;
        }

        set
        {
            if (value == this._fonts) return;
            this._fonts = value;
            NotifyPropertyChanged();
        }
    }


    public MainPage()
    {
        this.InitializeComponent();
        DataContext = this;

        Fonts = new List<string> {"Segoe UI", "Showcard Gothic", "Arial"};

        FontStyleText = Application.Current.Resources["textStyle"] as Style;

    }

    private void ListBox_SelectionChanged_1(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
    {
        var font = (sender as ListBox).SelectedItem as string;

        var res = new ResourceDictionary()
        {
            Source = new Uri("ms-appx:///Common/StandardStyles.xaml", UriKind.Absolute)
        };

        var style = res["textStyle"] as Style;

        style.Setters.RemoveAt(0); // if it is the first item otherwise for more accurat removal se below :D


        foreach (var item in style.Setters.Cast<Setter>().Where(item => item.Property == FontFamilyProperty))
        {
            style.Setters.Remove(item);
        }

        style.Setters.Add(new Setter(FontFamilyProperty, new FontFamily(font)));
        style.Setters.Add(new Setter(ForegroundProperty, new SolidColorBrush(Colors.Purple)));

        FontStyleText = style;

    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

6 个答案:

答案 0 :(得分:1)

由于TextBlock在StandardStyles.xaml中多次定义,因此无法正常工作的原因之一。如果您可以创建一个新的样式文档并在User控件的InitilizeComponent之前应用它,那么它将起作用。希望这能解释。

答案 1 :(得分:1)

尝试将ListBox_SelectionChanged_1方法更改为如下所示。无论出于何种原因,在将FontFamilyProperty设置添加到样式的设置器时,似乎都会抛出无声错误 - 或者至少在我切换时使用单独的视图模型时会出现这种错误。

    private void ListBox_SelectionChanged_1(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
    {
        var font = (sender as ListBox).SelectedItem as string;

        var res = new ResourceDictionary()
        {
            Source = new Uri("ms-appx:///Common/StandardStyles.xaml", UriKind.Absolute)
        };

        var style = res["textStyle"] as Style;
        var newStyle = new Style(style.TargetType);

        foreach (var setter in style.Setters.OfType<Setter>().Skip(1).Where(x => x.Property != TextBlock.FontFamilyProperty))
        {
            newStyle.Setters.Add(new Setter(setter.Property, setter.Value));
        }

        newStyle.Setters.Add(new Setter(TextBlock.FontFamilyProperty, new FontFamily(font)));
        newStyle.Setters.Add(new Setter(TextBlock.ForegroundProperty, new SolidColorBrush(Colors.Purple)));

        FontStyleText = newStyle;
    }

答案 2 :(得分:1)

Oki,所以我弄清楚出了什么问题。

非常感谢mlorbetske(以及Skype上的Matt),我注意到我遗漏的代码中有些东西。是的,很高兴地说这不是一个错误,但(大多数时候)缺少一些东西。没有收到错误消息是我会说的错误。

我缺乏正确的dependecyproperty - 目标属性设置错误。所以而不是:

style.Setters.Add(new Setter(FontFamilyProperty, new FontFamily(font)));

我不得不

style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, new FontFamily(font)));

就是这样:)

答案 3 :(得分:0)

根据我的经验,我只使用静态样式绑定,从不动态到数据上下文。样式通常在设计时创建并应用于多个项目以在整个应用程序中保持一致。

最好是拥有除了字体之外你需要的一个样式,有一个普通的静态绑定,然后只绑定字体(按名称应该在内存中工作)来覆盖样式。

答案 4 :(得分:0)

如果TextBlock的样式确实不能用于绑定 - 你可以简单地更新代码以将TextBlock放在DataTemplate中并添加/替换模板的实例化实例,当你拥有TextBlock时变化。

您还可以尝试添加Style类型的附加属性,并将其更改中继到实际的Style属性。

答案 5 :(得分:0)

嗯...我没有看到DataTrigger绑定 - 应该在Style / Style.Triggers下。您可能想尝试将触发器绑定到组合框 - 请查看以下链接:

Style.Triggers Property - MSDN

CodeProject Example on Style DataTriggers for TextBlock

MSDN Question on binding a TextBlock style to a combo box change

希望它有所帮助。

干杯,

亚瑟