2016-07-07 10 views
1

トリガーで矩形(WPF)の色を設定しようとしています(矩形のTagプロパティにバインドしているboolean DependencyPropertyによって異なります)。私は長方形のタグプロパティに "true" または "false"、トリガーが正しく動作ハードコードした場合プロパティを依存プロパティにバインドするときにトリガーが機能しない

<Window.Resources> 
    <Style x:Key="TriggerDark" TargetType="Rectangle"> 
     <Setter Property="Fill" Value="Green" /> 
     <Style.Triggers> 
      <Trigger Property="Tag" Value="False"> 
       <Setter Property="Fill" Value="Red" /> 
      </Trigger> 
      <Trigger Property="Tag" Value="True"> 
       <Setter Property="Fill" Value="Green" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

</Window.Resources> 

<Rectangle Style="{StaticResource ResourceKey=TriggerDark}" Tag="{Binding Path=isAutoStart, UpdateSourceTrigger=PropertyChanged}"> 

public partial class MainWindow : Window 
{ 
    public Boolean isAutoStart 
    { 
     get { return (Boolean)GetValue(isAutoStartProperty); } 
     set { SetValue(isAutoStartProperty, value); } 
    } 

    public static readonly DependencyProperty isAutoStartProperty = 
     DependencyProperty.Register("isAutoStart", typeof(Boolean), 
     typeof(MainWindow), new PropertyMetadata(true)); 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     isAutoStart = false; 
    } 
} 

とXAMLで:

私は、次のコードを持っています。 実行時にタグプロパティの値を実行時にコンソールに出力すると、バインディングは機能しますが、トリガは起動しません。

私が間違っていることは何ですか?

ありがとうございます!

+1

public static class StyleHelper { public static readonly DependencyProperty StateProperty = DependencyProperty.RegisterAttached( "State", typeof(bool), typeof(StyleHelper)); public static bool GetState(DependencyObject obj) { return (bool)obj.GetValue(StateProperty); } public static void SetState(DependencyObject obj, bool value) { obj.SetValue(StateProperty, value); } } 

としてあなたは、このようにXAMLでそれを使用しますWindowのDataContextをそれ自身に設定するか、BindingのRelativeSourceプロパティを指定します。それ以外に、UpdateSourceTriggerの設定は意味がありません。なぜなら、ここで効果がないからです。 – Clemens

+1

また、Tagプロパティをバインドせず、ValueにTriggerを設定するのではなく、isAutoStartプロパティに直接バインドするDataTriggerを使用することもできます。 – Clemens

+0

DataContextを設定しなかった場合は、 'Tag =" {Binding isAutoStart、RelativeSource = {RelativeSource AncestorType = Window}} "を試してください。 – Clemens

答えて

2

トリガはブール値trueと文字列 "True"を比較しようとします。これは、タグがObjectプロパティでブール値が格納され、トリガ値がStringであるためです。 PHPはWPFではなくそれを好きです。 ;)

あなたの代わりにDataTriggerのトリガを維持したい場合は、静的クラスを作成することができます

public static class BooleanHelper { 
    public static bool False { 
     get { return false; } 
    } 
    public static bool True { 
     get { return true; } 
    } 
} 

をそしてスタイルのように記述されます。Michael Mairegger

<Style x:Key="TriggerDark" TargetType="Rectangle"> 
    <Setter Property="Fill" Value="Green"/> 
    <Style.Triggers> 
     <Trigger Property="Tag" Value="{x:Static local:BooleanHelper.True}"> 
      <Setter Property="Fill" Value="Red" /> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

クレジットアイデアに

+0

ありがとう、これは完璧に動作します。 :) – Niki

1

あなたはDataTriggerを使用して試みることができる:

(トリガーを削除し、あなたも自分のスタイルをsemplifyできることに注意してください)も

 <Style x:Key="TriggerDark" TargetType="Rectangle"> 
      <Setter Property="Fill" Value="Green" /> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding Path=isAutoStart}" Value="False"> 
        <Setter Property="Fill" Value="Red" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 

設定ウィンドウへのDataContext:

public MainWindow() 
{ 
    DataContext = this; 
} 

編集: 必要に応じてIValueConverterを使用できます。

public class BoolToStringConverter : IValueConverter 
{ 

    public object Convert(object value, Type targetType, object parameter, 
     System.Globalization.CultureInfo culture) 
    { 
     if (targetType != typeof(bool)) 
      throw new InvalidOperationException("The target must be a boolean"); 

     return value.ToString(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
     System.Globalization.CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 

} 

そしてへの結合を変更します。

<Window.Resources> 
     <local:BoolToStringConverter x:Key="BtSConv"/> 
     <Style x:Key="TriggerDark" TargetType="Rectangle"> 
      <Setter Property="Fill" Value="Green" /> 
      <Style.Triggers> 
       <Trigger Property="Tag" Value="False"> 
        <Setter Property="Fill" Value="Red" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 

    </Window.Resources> 
    <Rectangle Style="{StaticResource TriggerDark}" Tag="{Binding isAutoStart, Converter={StaticResource BtSConv}}" /> 

でも他人からあなたのための美しい解決策がたくさんあります。

+0

私はこれを再利用したいので、DataTriggerで依存関係プロパティを直接バインドしたくありません"template"を呼び出し、Tagプロパティ内の別の依存関係プロパティを渡すだけです。 – Niki

1

バインディングのDataContextを設定する必要があります。あなたのバインディングはRectangle.DataContext.isAutoStartを指していますが、Rectangle.DataContextはnullなので、バインディングは何にも解決されません。 DataContextの詳細については、this answerを参照してください。

あなたはDataTriggerをハードコーディングしたくないあなたはhereを述べているので、あなたはおそらく、手動ではなく、最初のWindowオブジェクトにビジュアルツリーを検索するバインディングのSourceを設定したい、とのisAutoStartプロパティにバインドしますそれ。あなたは文字列にブール値を比較しているthis answerで指摘したように

<Rectangle Tag="{Binding Path=isAutoStart, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" .. /> 

はまた、余分な問題を抱えているので、それはいつものようにFalseに評価されます。そこなIValueConverterとして、この周りには多くの方法が、ですが、私はhere示すように、最も単純には、System名前空間をインポートし、ブール真の静的値を作成することです見つける:

s名前空間が

のように定義されて
<s:Boolean x:Key="TrueValue">True</s:Boolean> 
... 
<Trigger Property="Tag" Value="{StaticResource TrueValue}"> 

xmlns:s="clr-namespace:System;assembly=mscorlib" 
1

ユーザーnkoniishvtはすでに説明を与えている、トリガーは、文字列リテラル「true」と「false」の代わりbool値にTagプロパティの値を比較します。

この問題の別の回避策は、Tagプロパティを使用するのではなく、正しくタイプされた添付プロパティです(例:あなたは、例えば、ソースオブジェクトを設定しない限り、バインディング動作しません

<Window.Resources> 
    <Style TargetType="Rectangle"> 
     <Setter Property="Fill" Value="Green" /> 
     <Style.Triggers> 
      <Trigger Property="local:StyleHelper.State" Value="False"> 
       <Setter Property="Fill" Value="Red" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</Window.Resources> 

<Rectangle local:StyleHelper.State="{Binding isAutoStart}}" /> 
関連する問題