3

要するに:私は持っていStyleます。TemplateBinding何度も何度も繰り返すのではなく、かなりの量を使用してパラメーター化します。ただし、そのスタイルのトリガーが使用され、リソースがそのトリガーのセッターで使用されると、それは表示されません! デフォルト値すら表示されません。この問題を再現する小さなプログラムを次に示します。

TestDictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:lcl="clr-namespace:MyNamespace">
    <Style TargetType="Button" x:Key="BtnTest">
        <Style.Resources>
            <Label Content="{TemplateBinding lcl:TestClass.String}" x:Key="innerLabel"/>
        </Style.Resources>
        <Style.Triggers>
            <Trigger Property="IsEnabled" Value="True">
                <Setter Property="Content" Value="{DynamicResource innerLabel}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

MainWindow.xaml

<Window x:Class="MyNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:lcl="clr-namespace:MyNamespace"
        Title="Test" Width="500" Height="350">
    <Window.Resources>
        <ResourceDictionary Source="TestDictionary.xaml"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Content="Enable/Disable" Click="Click"/>
        <Button Grid.Column="1" x:Name="btn" Style="{DynamicResource BtnTest}" lcl:TestClass.String="TESTING"/>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;

namespace MyNamespace
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Click(object sender, RoutedEventArgs e)
        {
            btn.IsEnabled = !btn.IsEnabled;
        }
    }
    public class TestClass
    {
        public static string GetString(DependencyObject obj)
        {
            return (string)obj.GetValue(StringProperty);
        }

        public static void SetString(DependencyObject obj, string value)
        {
            obj.SetValue(StringProperty, value);
        }
        public static readonly DependencyProperty StringProperty =
            DependencyProperty.RegisterAttached("String", typeof(string), typeof(TestClass), new PropertyMetadata("Default!"));
    }
}

を使用する代わりにTemplateBinding、これも試しました:

{Binding Path=lcl:TestClass.String, RelativeSource={RelativeSource AncestorType={x:Type Button}}}

それでもうまくいきませんでした。私はおそらく何か間違ったことをしていることを知っていますが、問題は次のとおりです。それは何ですか?

4

3 に答える 3

1

これを機能させるために本当に必要なRelativeSourceのは、バインディングで使用することだけです。に添付プロパティを設定しているためButton、スタイル トリガーで、自分自身の添付プロパティにバインドできます。

<Style TargetType="Button" x:Key="BtnTest">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Content" 
                    Value="{Binding Path=(lcl:TestClass.String), RelativeSource={RelativeSource Self}}"/>
        </Trigger>
    </Style.Triggers>
</Style>

あなたのアプローチを使用することの1つのクールな点Buttonは、ContentControl添付されたプロパティが文字列だけでなく、任意のオブジェクトになる可能性があるためです。

そして、以前のアプローチで何がうまくいかなかったのかを明確にするために-

  • 他の人が言ったように、でTemplateBindingのみ動作しControlTemplatesます。また、テンプレートを作成しているクラスで が定義されている場合にのみ機能します (したがって、たとえばtoをDependencyProperty実行することはできません)。TemplateBindingGrid.Row
  • 添付プロパティにバインドする場合、全体を括弧で囲む必要があります。そうしないと、WPF はプロパティのプロパティにバインドしようとします。そうでなければ、あなたのRelativeSourceバインディングは近かったです!
  • Labelコンテンツとして内部を持ちたい場合はButtonうまくいくかもしれませんが(私はそれをテストしませんでした)、Button必要なオブジェクトをホストできるため、最良のアイデアとは思えません。

より複雑な例の編集

したがって、複数の動的プロパティを表示する必要がある場合は、次を使用することをお勧めしますDataTemplate

<Style TargetType="Button" x:Key="BtnTest">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Label Content="{Binding Path=(lcl:TestClass.String), RelativeSource={RelativeSource AncestorType={x:Type Button}}}" />
                    </DataTemplate>
                </Setter.Value>
            </Setter> 
        </Trigger>
    </Style.Triggers>
</Style>

DataTemplateSelectorまた、コンテンツの外観を変更するための基準が複数ある場合は、a の方が適している可能性があることを指摘しておきます。

于 2013-06-25T20:02:55.047 に答える
0

TemplateBindingでのみ機能するため、例は機能しませんControlTemplate。に似た何かを達成するには、他のことTemplateBindingResourcesする必要があります。これが例です。

が機能するためTemplateBindingには、コードを少し修正する必要があります (これはリソースのない単なる例です)。

<Style x:Key="BtnTest" TargetType="{x:Type Button}">
    <Setter Property="MinHeight" Value="100" />
    <Setter Property="MinWidth" Value="200" />
    <Setter Property="BorderThickness" Value="2" />
    <Setter Property="BorderBrush" Value="Blue" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" Background="{TemplateBinding Background}">
                    <ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding lcl:TestClass.String}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Opacity" Value="0.5" />
        </Trigger>
    </Style.Triggers>
</Style>

このトピックに関する便利なリンク:こことここも。

編集:

の代わりにアプリケーション設定を使用することもできますTestClass。「プロジェクト -> プロパティ: MyNamespace... -> 設定」を開き、設定を追加します。

名前--------タイプ--------スコープ--------

LabelText---文字列--------ユーザー----------デフォルト

LabelTextin コードの値を設定します。例えば:

    public MainWindow()
    {
        InitializeComponent();

        MyNamespace.Properties.Settings.Default.LabelText = "Testing";
    }

そして、この ResourceDictionary を使用します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:properties="clr-namespace:MyNamespace.Properties"
                xmlns:lcl="clr-namespace:MyNamespace">

<Style TargetType="Button" x:Key="BtnTest">
    <Style.Resources>
        <Label x:Key="innerLabel" Content="{Binding Source={x:Static properties:Settings.Default}, Path=LabelText, Mode=TwoWay}" />
    </Style.Resources>

    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Content" Value="{DynamicResource innerLabel}"/>
        </Trigger>
    </Style.Triggers>
</Style>

于 2013-06-22T19:07:16.987 に答える