当UserControl的TextBox为空时禁用MenuItem

时间:2015-06-11 11:16:20

标签: wpf binding textbox user-controls menuitem

在我的主Window我有一个MenuItem和一个UserControl。如果MenuItem中的一个TextBoxes分别为空/非空,我想禁用/启用UserControl

如果UserControl名为ContactDetailsTexBox名为ContactNameTextBox,请参阅MenuItem我的xaml代码:

<MenuItem x:Name="DeleteContact" 
          Header="Delete Contact" 
          IsEnabled="{Binding ElementName=ContactDetails.ContactNameTextBox,Path=Text.Length, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

出于某种原因,MenuItem始终保持启用状态。我错过了什么?

2 个答案:

答案 0 :(得分:0)

你绑定到文本的长度但你需要一个从长度到bool的转换器,因为IsEnabled属性需要一个bool。

public class NumToBoolConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter,    System.Globalization.CultureInfo culture) 
    { 
       if (value!=null && value is int ) 
       {
          var val = (int)value; 
          return (val==0) ? false : true; 
       } 
       return null; 
    } 


    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
       if (value!=null && value is bool ) 
       { 
         var val = (bool)value; return val ? 1 : 0;
       } 
       return null; 
    }
}

为此添加本地xmlns和资源。

 xmlns:local="clr-namespace:YourNamespace"

这是对转换器类的引用。

<local:NumToBoolConverter x:Key="NumToBoolConverter"/>

在你的Binding部分添加:

 Converter={StaticResource NumToBoolConverter}

这可能是您最终的MenuItem定义:

        <MenuItem x:Name="DeleteContact" 
                  Header="Delete Contact"
                  IsEnabled="{Binding ElementName=ContactDetails.ContactNameTextBox,
                                      Path=Text.Length, 
                                      Converter={StaticResource NumToBoolConverter},
                                      Mode=TwoWay, 
                                      UpdateSourceTrigger=PropertyChanged}"/>

答案 1 :(得分:0)

绑定存在一些问题。首先是您指定了双向绑定。这意味着您要回写文本框中的“length”属性。因为它是readonly你不能。

通常你应该得到一个错误:

  

TwoWay或OneWayToSource绑定无法在只读模式下运行   'System.String'类型的属性'Length'。

奇怪的是,绑定确实在那之后起作用。但这真的不是正确的方法。 .NET的神奇之处在于允许将0解释为“false”。但它不是一个安全的约束力。正如Olaru在他的回答中所说,length属性是一个整数,IsEnabled字段正在寻找一个bool。如果您想绑定到'visibility'属性怎么办?

那么处理这个问题的最佳方法是什么?转换器绝对是一种选择,在许多情况下是最佳选择。转换器的优点是它们可以在类似的情况下重复使用。我们有一个充满了我们经常使用的转换器的库。 Olaru已经描述了如何做到这一点,所以我不会重复他已经说过的话。

在某些情况下,了解不同的方式是有益的。数据触发器将允许您执行与转换器相同的操作。这是一种单向约束。这是一个例子。

<MenuItem x:Name="DeleteContact"  Header="Delete Contact">
   <MenuItem.Style>
       <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
         <Setter Property="MenuItem.IsEnabled" Value="true"/>
         <Style.Triggers>
           <DataTrigger Binding="{Binding Text.Length, ElementName=ContactNameTextBox}" Value="0">
               <Setter Property="MenuItem.IsEnabled" Value="false"/>
           </DataTrigger>
         </Style.Triggers>
       </Style>
    </MenuItem.Style>
  </MenuItem>

无需代码!!

关于转换器和数据触发器的优缺点,有很多争论。但最重要的是要知道有多种方法可以做你要求的事情。