WPF在MVVM视图模型

时间:2016-03-24 22:20:07

标签: wpf mvvm wpf-controls visibility datatemplate

我有一个设置为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中有一个控件,我希望从各种视图模型中设置Visibility:

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

这是我的依赖属性。它出现在intelliesense中,因此CLR已正确注册,但它没有获取属性赋值(忽略Collapsed)。

这让我感觉非常接近,但我记得有人告诉我我不能这样做,因此EventTriggers(这显然是datatemplates和MVVM的常见问题)。

所以一个选择是在Interaction名称空间中使用某些内容,就像我执行我的事件触发器一样(我只需要以某种方式触发此按钮上的“可见性”触发器,至少我认为)。

什么是正确在MVVM中执行此操作的方法是什么?

1 个答案:

答案 0 :(得分:0)

修复代码

为了使您现有的代码工作,您需要告诉需要告诉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。