【问题标题】:Disable a MenuItem when TextBox of UserControl is empty当 UserControl 的 TextBox 为空时禁用 MenuItem
【发布时间】:2015-08-27 01:25:05
【问题描述】:

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

给定一个名为ContactDetailsUserControl 和一个名为ContactNameTextBoxTexBox,这是我的MenuItem 的xaml 代码:

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

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

【问题讨论】:

    标签: wpf binding textbox user-controls menuitem


    【解决方案1】:

    您正在绑定到文本的长度,但您需要一个将长度转换为布尔值的转换器,因为 IsEnabled 属性需要一个布尔值。

    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"/>
    

    在你的绑定部分添加这个:

     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}"/>
    

    【讨论】:

      【解决方案2】:

      您的绑定存在一些问题。第一个是您指定了双向绑定。这意味着您要写回文本框中的“长度”属性。因为它是只读的,所以你不能。

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

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

      现在很奇怪,绑定在那之后确实起作用了。但这真的不是正确的方法。 .NET 的魔力在于允许将 0 解释为“假”。但这不是一个安全的绑定。正如 Olaru 在他的回答中所说,长度属性是一个整数,而 IsEnabled 字段正在寻找一个布尔值。如果您想绑定到“可见性”属性怎么办?

      那么处理这个问题的最佳方法是什么?转换器绝对是一种选择,在许多情况下也是最佳选择。转换器的优点是它们可以在类似情况下重复使用。我们有一个库,里面装满了我们经常使用的转换器。 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>
      

      无需代码!!

      关于转换器和数据触发器的优缺点有很多争论。但最重要的是要知道有不止一种方法可以满足您的要求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-03
        • 2012-02-21
        • 2015-02-16
        • 2019-04-22
        • 2011-01-14
        • 2015-11-23
        • 2020-02-18
        相关资源
        最近更新 更多