2016-10-06 12 views
1

コントロールBを含むコントロールAがある場合、継承されるプロパティーはPropです。つまり、B.Propが明示的にに設定されていない場合、B.Propは自動的にA.Propの値を取ります。私の知る限り、IsEnabledはこのようなプロパティです。明示的に設定されていても、親によってプロパティ値がオーバーライドされます

今私はB.IsEnabledの値を明示的に設定していて、それでもA.IsEnabledの値で上書きされている状況があります。 それはなぜですか、どうすれば修正できますか?このような状況A

はStackPanelのであるとBテキストボックス:

<StackPanel> 
    <StackPanel.Style> 
     <Style TargetType="StackPanel"> 
      <Setter Property="IsEnabled" Value="True"/> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding InDisableMode}" Value="True"> 
        <Setter Property="IsEnabled" Value="False"/> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </StackPanel.Style> 
    <TextBox Text="some text"> 
     <TextBox.Style> 
      <Style TargetType="TextBox"> 
       <Setter Property="IsEnabled" Value="False"/> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding InDisableMode}" Value="True"> 
         <Setter Property="IsEnabled" Value="True"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </TextBox.Style> 
    </TextBox> 
</StackPanel> 

上記のXAMLのスニペットはそのDataContextのが私のViewModelに設定されています。 ViewModelには、boolのプロパティInDisableModeが含まれています。 falseの場合、すべてが期待どおりです。StackPanelが有効で、TextBoxが無効です。

InDisableModetrueの場合、両方のトリガーはトリガーする必要がありますが、StackPanelとTextBoxの両方が無効になります。

注:両方のコントロール(TextBox内で、補完コンバータを使用してStackPanelで直接)のIsEnabledInDisableModeをデータバインドできることはわかっています。とにかくこれをTriggersでやってみたいので、これがうまくいくと私は試していません。

EDIT:のStackPanelを無効にする

ポイントは(私が代わりに使用可能にしたいテキストボックスを除く)簡単にその子のすべてを無効にすることです。親子関係を変更したり、新しいコントロールを作成したりせずにこのタスクを解決する方法は他にもありますか?現時点では、私が見る唯一の方法は、TextBoxを除くすべての子を無効にすることです。

答えて

1

コントロールを無効にすると、その子は無効になります。 StackPanelは対話型ではないため、対話型の子を無効にする以外に無効にする必要はありません。

親Bが無効の状態でコントロールAを有効にしたい場合は、その操作はできません。 Bを無効にしているときにAを有効にするには、Bを親にすることはできません。この問題を回避するために

、あなたはStackPanelの上にTextBoxを重畳する、最後に定義TextBoxで、両方Gridでそれらを置くことができます。それはStackPanelの領域内にありますが、それはStackPanelの子ではありません。

1

これは、UIElement.IsEnabledプロパティが、親からの値を継承して値強制を使用するためです。これはCoerceValueCallbackを使用して行います。値の強制は、最初にランク付けされますDependency Property Setting Precedence List.

したがって、この動作を無効にするには2つの方法があります。まず、AddOwner()を使用して、IsEnabledプロパティの新しい所有者として私たちのタイプを登録してください。次に、OverrideMetadata()を使用してメタデータをオーバーライドします。この2番目の方法は、UIElementから直接継承した場合にのみ機能します。

ので、私たちは私たちのButtonは異なる動作をしたいと、私たちは以下のような新しいButtonを作成する必要があります。ここでは

public class CButton : Button 
{ 
    public static readonly DependencyProperty IsEnabled; 

    static CButton() 
    { 
     IsEnabled = UIElement.IsEnabledProperty.AddOwner(typeof(CButton), 
       new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.None, 
        UIElement.IsEnabledProperty.DefaultMetadata.PropertyChangedCallback, 
        new CoerceValueCallback(IsEnabledCoerceCallback))); 
    } 

    private static object IsEnabledCoerceCallback(DependencyObject d, object baseValue) 
    {    
     return (bool) baseValue; 
    } 
} 

それはIsEnabledCoerceCallbackからであるように、我々は、割り当てられた値を返しています。返される前に、あなたも動作を導入することができます:ユーザがIsEnabledの値を提供しない場合は、親からの継承した値を使用します。それ以外の場合は、CButton.IsEnabledのユーザ割り当て値を使用します。

new CoerceValueCallback(IsEnabledCoerceCallback)の代わりにnullを設定してみてください。何が起こるかをご覧ください。

+0

"これは、UIElement.IsEnabledプロパティが親からの値を継承して値強制を使用するためです。 - しかし、子が親から常にその値を継承する場合、親を有効にして子を無効にすることは可能ですか? – Kjara

+1

@Kjara継承と上書きは2つの違いがあります。強制は、デフォルトの動作を上書きすることを意味します。 Label.FontSize = 20は、その中のすべてのテキストブロックのフォントサイズを変更しますが、FontSizeを特定のフォントサイズに設定すると、それが尊重されます。 – AnjumSKhan

関連する問題