Wpf 当UserControl的文本框为空时禁用菜单项
在我的主Wpf 当UserControl的文本框为空时禁用菜单项,wpf,binding,textbox,user-controls,menuitem,Wpf,Binding,Textbox,User Controls,Menuitem,在我的主窗口中有一个菜单项和一个用户控件。如果UserControl中的文本框之一分别为空/非空,我想禁用/启用MenuItem 给定一个名为ContactDetails的UserControl和一个名为ContactNameTextBox的TexBox,下面是我的菜单项的xaml代码: <MenuItem x:Name="DeleteContact" Header="Delete Contact" IsEnabled="{Binding Ele
窗口中
有一个菜单项
和一个用户控件
。如果UserControl
中的文本框之一分别为空/非空,我想禁用/启用MenuItem
给定一个名为ContactDetails
的UserControl
和一个名为ContactNameTextBox
的TexBox,下面是我的菜单项的xaml代码:
<MenuItem x:Name="DeleteContact"
Header="Delete Contact"
IsEnabled="{Binding ElementName=ContactDetails.ContactNameTextBox,Path=Text.Length, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
由于某些原因,MenuItem
始终保持启用状态。我缺少什么?您正在绑定文本的长度,但需要从长度到布尔值的转换器,因为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"
这是对converter类的引用
<local:NumToBoolConverter x:Key="NumToBoolConverter"/>
这可以是您的最终菜单项定义:
<MenuItem x:Name="DeleteContact"
Header="Delete Contact"
IsEnabled="{Binding ElementName=ContactDetails.ContactNameTextBox,
Path=Text.Length,
Converter={StaticResource NumToBoolConverter},
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
您的绑定有几个问题。首先,您指定了一个双向绑定。这意味着您希望回写文本框中的“length”属性。因为它是只读的,所以你不能
通常情况下,您会得到一个错误:
双向或单向ToSource绑定无法在只读服务器上工作
类型为“System.String”的属性“Length”
奇怪的是,在那之后绑定就开始工作了。但这确实不是正确的方法。NET的神奇之处在于允许将0解释为“false”。但这不是一个安全的约束。正如Olaru在回答中所说,length属性是一个整数,IsEnabled字段正在寻找布尔值。如果要绑定到“可见性”属性,该怎么办
那么,处理这个问题的最佳方法是什么呢?转换器绝对是一种选择,在许多情况下是最佳选择。转换器的优点是可以在类似情况下重复使用。我们有一个我们经常使用的转换器库。奥拉鲁已经描述了如何做到这一点,所以我不会重复他已经说过的话
但在某些情况下,了解不同的方法是有益的。datatrigger将允许您执行与转换器相同的操作。这是一种单向绑定。这里有一个例子
<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>
不需要代码
关于转换器和数据触发器的利弊有很多争论。但最重要的是要知道有不止一种方法可以满足你的要求
<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>