我有一个设置为DataTemplate:的控件
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<DataTemplate x:Key="KEYBOARD_EN">
<StackPanel>
<Button Visibility="{Binding Path=RegisterButtonVisible}" Style="{StaticResource RegisterKeyboardButtonStyle}">Register</Button>
</StackPanel>
</DataTemplate>
在这个DataTemplate中,有一个控件,我希望从各种视图模型中设置可见性:
<Button Visibility="{Binding Path=RegisterButtonVisible}" Style="{StaticResource ...} > Register </Button>
我确实用我的控件路由事件,所以我尝试设置类似的东西,但无论我尝试什么,RegisterButtonVisible属性都不会被选中:
public partial class MainKeyboard : UserControl
{
public static DependencyProperty RegisterButtonVisibleProperty;
public Visibility RegisterButtonVisible
{
get { return (Visibility)GetValue(RegisterButtonVisibleProperty); }
set { SetValue(RegisterButtonVisibleProperty, value); }
}
static MainKeyboard()
{
RegisterButtonVisibleProperty = DependencyProperty.Register("RegisterButtonVisible", typeof (Visibility),
typeof (MainKeyboard));
}
}
在我的ViewModel中,我这样做:
public Visibility RegisterButtonVisible // get, set, raisepropchange, etc
我的DataTemplate中有一个按钮,它被包装在一个userControl:中
<UserControl x:Class="Bleh.Assets.MainKeyboard"
x:Name="TheControl"
Unloaded="UserControl_Unloaded">
<Viewbox>
<Grid>
<ContentControl Name="ctrlContent" Button.Click="Grid_Click" />
</Grid>
</Viewbox>
在我的观点中是这样使用的:
<assets:MainKeyboard
RegisterButtonVisible="Collapsed"
Loaded="MainKeyboard_Loaded">
<b:Interaction.Triggers>
<b:EventTrigger EventName="Register">
<b:InvokeCommandAction Command="{Binding ConfirmEmailAddressCommand}"/>
</b:EventTrigger>
<b:EventTrigger EventName="Enter">
<b:InvokeCommandAction Command="{Binding EnterKeyCommand}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</assets:MainKeyboard>
请注意此属性:
RegisterButtonVisible="Collapsed"
这是我的依赖属性。它显示在intellisense中,因此CLR已正确注册它,但它不会获取属性分配(Collapsed被忽略)。
这让我觉得它非常接近,但我确实记得有人告诉我我不能这样做,因此EventTriggers(这显然是数据模板和MVVM的常见问题)。
因此,一种选择是在Interaction命名空间中使用一些东西,就像我做事件触发器一样(我只需要以某种方式在这个按钮上触发一个"可见性"触发器,至少我想是这样)。
什么是正确的在MVVM中有任何方法可以做到这一点?
修复代码
为了使您现有的代码能够工作,您需要告诉WPF应该从哪个对象RegisterButtonVisible
中读取。如果是用户控件,则为UserControl
指定一个名称,然后通过ElementName
引用该元素,如下所示:
<UserControl ... lots of stuff here
x:Name="TheControl"
>
在您的按钮绑定中:
<Button Visibility="{Binding ElementName=TheControl, Path=RegisterButtonVisible}" Style="{StaticResource RegisterKeyboardButtonStyle}">Register</Button>
当然,如果因为按钮和用户控件在不同的文件中而无法做到这一点,那么您仍然可以使用祖先绑定:
<Button Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type assets:MainKeyboard}},
Path=RegisterButtonVisible}"
Style="{StaticResource RegisterKeyboardButtonStyle}">Register</Button>
对于每个按钮,它将向上查找最近的assets:MainKeyboard
实例,然后绑定到RegisterButtonVisible
属性。
使用MVVM
如果你想使用MVVM(而不是在控件上)实现同样的效果,你需要使用转换器将布尔值转换为可见性属性,比如:
<Button Visibility="{Binding IsRegistrationAllowed, Converter={StaticResource BoolToVis}}" Style="{StaticResource RegisterKeyboardButtonStyle}">Register</Button>
当然,这是假设DataContext设置正确并指向ViewModel。