3

私にとってSOの新年の早いスタート:)

簡単なことだと思っていた友達を助けようとしています。基本的には、実行時にコードでスタイルを変更し、TextBlockのスタイルを更新するだけです。

TextBlockを除いて、他のタイプの要素でこれを機能させるのに問題はありませんでした。ここで何かを見逃したのか、それとも実際にバグがあるのか​​、私は今非常に興味があります。これを解決するための最も良い方法は何でしょうか?

ここでのコードはデモンストレーション用であり、TextBoxでは機能しますがTextBlockでは機能しません(もちろんtargettypeなどが変更された場合)

Commonフォルダーの下のStandardStylesと呼ばれるリソース辞書で定義されたスタイル

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

UI

    <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));
        }
    }
}
4

6 に答える 6

1

TextBlockがStandardStyles.xamlで何度も定義されているために、機能しなかった理由の1つ。新しいスタイルのドキュメントを作成し、それをユーザーコントロールのInitilizeComponentの前に適用できれば、それは機能します。これが説明することを願っています。

于 2013-01-02T18:52:48.337 に答える
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;
    }
于 2013-01-02T18:58:24.197 に答える
1

沖、それで私は何が悪いのかを理解しました。

そのためにmlorbetske(そしてskypeのMatt)に大いに感謝します、私は私が欠けていたコードの一部に何かに気づきました。そして、はい、それはバグではなく、(ほとんどの場合)何かが欠けていると言って幸せです。エラーメッセージが表示されないのはバグだと思います。

私は正しいdependecypropertyを欠いていました-ターゲットプロパティが間違って設定されました。したがって、代わりに:

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

そうしなければならなかった

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

それでおしまい :)

于 2013-01-02T19:27:22.730 に答える
0

私の経験では、静的なスタイルのバインディングのみを使用し、データコンテキストに対して動的なものは使用していません。スタイルは、通常はデザイン時に作成され、アプリ全体で一貫性を保つために複数のアイテムに適用されるものです。

フォント以外の必要なものすべてを備えたスタイルを用意し、通常の静的バインディングを使用してから、フォントのみをバインドして(名前はメモリから機能するはずです)、スタイルをオーバーライドする方がよい場合があります。

于 2013-01-02T18:13:03.747 に答える
0

TextBlockのスタイルが実際にバインディングで機能しない場合は、コードを更新してTextBlockをDataTemplateに配置し、スタイルが変更されたときにTextBlockがあるテンプレートのマテリアライズドインスタンスを追加/置換できます。

また、Styleタイプの添付プロパティを追加して、その変更を実際のStyleプロパティに中継することもできます。

于 2013-01-02T18:30:23.587 に答える
0

うーん...DataTriggerバインディングが表示されません-Style/Style.Triggersの下にあるはずです。トリガーをコンボボックスにバインドしてみてください。次のリンクをご覧ください。

Style.Triggersプロパティ-MSDN

TextBlockのスタイルDataTriggersのCodeProjectの例

TextBlockスタイルをコンボボックスの変更にバインドすることに関するMSDNの質問

それが役に立てば幸い。

乾杯、

アーサー

于 2013-01-02T19:03:27.370 に答える