2

短いバージョン: WPF は、コンバーターが を返す場合でも、バインドで
を使用する場合、常にローカル値を設定するようです。 私の質問は次のとおりです。継承された値を使用するように WPF に指示するには、何を返すか、何をする必要がありますか?IValueConverterBinding.DoNothing

注: DataTriggers を使用したくないのは、現在のコンバーターが返すすべての色に対してコンバーターと共に 1 つのデータ トリガーが必要になるため、コードが大幅に肥大化するためです。


再生付きのロングバージョン:

次のシナリオを想像してください:
aが配置ButtonされているTextBlockがあります。Buttonプロパティを設定する のスタイルが存在しForegroundます。この値は によって継承されますTextBlockTextBlockここで、の値を aBrushに変換して - として使用する値コンバーターを作成したいと考えていますが、Foreground場合によってはのみです。特別な色を設定したくない場合は、 を返しBinding.DoNothingます。私の理解では、これによりTextBlock、継承された値を引き続き使用することができます。

残念ながら、私の理解は正しくありませんでした。Binding.DoNothingローカル値を返すように設定されている場合でも。これは Snoop で確認済みです。

この問題は、次の簡単な例で簡単に再現できます。

XAML:

<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <WpfApplication1:DummyConverter x:Key="DummyConverter" />
    <Style TargetType="{x:Type Button}">
      <Setter Property="Foreground" Value="Red" />
    </Style>
    <Style TargetType="{x:Type TextBlock}">
          <Setter Property="Foreground"
                  Value="{Binding Path=Text, RelativeSource={RelativeSource Self}, Converter={StaticResource DummyConverter}}" />
    </Style>
  </Window.Resources>
  <StackPanel>
    <Button><TextBlock>Text1</TextBlock></Button>
    <Button><TextBlock>Text2</TextBlock></Button>
  </StackPanel>
</Window>

コンバータ:

public class DummyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value.ToString() == "Text2")
            return Brushes.Cyan;
        return Binding.DoNothing;
    }
}

ご覧のとおり、最初のボタンのテキストは赤ではなく黒です。TextBlock両方のボタンのスタイルを削除すると、正しい赤いテキストが表示されます。

質問:
これを防ぐにはどうすればよいですか? 継承された値を引き続き使用するようにエンジンに指示する、返す値はありますか?

4

2 に答える 2

3

あなたの質問に答えるには:このスレッドによると、いいえ。TextBlock にスタイル セッターを指定すると (#4)、返された値は継承されたプロパティをオーバーライドします (#7)。

代わりに、次のように MultiBinding を作成できます。

public class DummyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values[0].ToString() == "Text2")
            return Brushes.Cyan;

        return values[1];
    }
}

<Window x:Class="Spritefire.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Spritefire"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:DummyConverter x:Key="DummyConverter" />
        <Style TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Foreground">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource DummyConverter}">
                        <Binding Path="Text" RelativeSource="{RelativeSource Self}" />
                        <Binding Path="Foreground" ElementName="ExampleButton" />
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button x:Name="ExampleButton">
            <TextBlock>Text1</TextBlock>
        </Button>
        <Button>
            <TextBlock>Text2</TextBlock>
        </Button>
    </StackPanel>
</Window>
于 2012-07-20T13:16:51.070 に答える
1

私はそれを機能させましたが、この解決策は良くなく、少しにおいがします...それでも投稿します。

次のようにカスタム添付プロパティを宣言します。

 public static class CustomForeground
{
    public static readonly DependencyProperty CustomForegroundProperty = DependencyProperty.RegisterAttached(
                      "CustomForeground",
                      typeof(Brush),
                      typeof(CustomForeground),
                      new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender, OnChange));

    public static void SetCustomForeground(UIElement element, Brush value)
    {
        element.SetValue(CustomForegroundProperty, value);
    }

    public static void OnChange(DependencyObject d, DependencyPropertyChangedEventArgs arg)
    {
        if (arg.NewValue != null)
            d.SetValue(TextBlock.ForegroundProperty, arg.NewValue);
    }
}

およびテキスト ボックスのスタイル:

<Style TargetType="{x:Type TextBlock}">
        <Setter Property="WpfApplication1:CustomForeground.CustomForeground"
              Value="{Binding Path=Text, RelativeSource={RelativeSource Self}, Converter={StaticResource DummyConverter}}" />
    </Style>

これは現時点で私の頭に浮かぶ唯一のことであり、ボタンのテキストが変更されていないと仮定すると機能します。その場合は、別の添付プロパティで Foreground のデフォルト値を記憶し、else ステートメントで設定する必要があります。

于 2012-07-20T13:00:42.270 に答える