如何从另一个控件中绑定到自定义控件按钮可见性

时间:2014-01-04 19:07:06

标签: c# wpf mvvm

我有一个自定义控件,它有一个按钮:

<UserControl x:Class="Gambit.Views.FileSelectionControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    SnapsToDevicePixels="True" 
    mc:Ignorable="d">
    ...
    <Button Content="Load" 
            Margin="5,5,5,5" 
            Height="22" 
            Width="70" 
            IsDefault="True" 
            IsEnabled="{Binding SelectedFileExists}" 
            AttachedCommand:CommandBehavior.Event="Click" 
            AttachedCommand:CommandBehavior.Command="{Binding CloseDialogCommand}"/>
    ...
</UserControl>

我想在另一个控件中包含此控件,但我想在主机控件中设置Load按钮的可见性;

之类的东西
<UserControl x:Class="Gambit.Views.SomeOtherControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    SnapsToDevicePixels="True" 
    mc:Ignorable="d">
    ...
    <GroupBox Header="Select Test Data">
        <Views:FileSelectionControl <Here Set the Load Button Visibility>/>
    </GroupBox>
    ...
</UserControl>

其中<Here Set the Load Button Visibility>显示我想要设置控件可见性的位置。如何完成[不破坏MVVM模式]?

感谢您的时间。

3 个答案:

答案 0 :(得分:5)

您可以在DependencyProperty

中创建UserControl
public partial class SomeView : UserControl
{
    ...

    public static DependencyProperty ButtonVisibilityProperty = DependencyProperty.Register("ButtonVisibility", typeof(Visibility), typeof(SomeView));

    public Visibility ButtonVisibility
    {
        get { return (Visibility)GetValue(ButtonVisibilityProperty); }
        set { SetValue(ButtonVisibilityProperty, value); }
    }
}

将其绑定到Button.Visibility

<UserControl x:Class="WpfApplication2.SomeView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d">
    <Button Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=ButtonVisibility}" Content="My Button"/>
</UserControl>

然后你就可以从外面控制Visibility

<local:SomeView ButtonVisibility="Collapsed"/>

因为它是DependencyProperty,您也可以使用Binding

答案 1 :(得分:2)

您只需在UserControl1中创建一个bool或Visibility Type属性,并将其设置为Usercontrol2,如

  

UserControl1 xaml

<UserControl x:Class="WpfApplication4.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <Button x:Name="Loadbutton" Content="load"/>
</Grid>

  

xaml.cs

 public UserControl1()
    {
        InitializeComponent();
    }

    bool showLoadButton;
    public bool ShowLoadButton
    {
        get { return showLoadButton; }
        set
        {
            showLoadButton = value;
            if (showLoadButton)
                Loadbutton.Visibility = Visibility.Visible;
            else
                Loadbutton.Visibility = Visibility.Collapsed;
        }

    }
  

UserControl2将ShowLoadButton设置为True或false

<UserControl x:Class="WpfApplication4.UserControl2"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WpfApplication4"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <local:UserControl1 ShowLoadButton="True"/>
</Grid>

答案 2 :(得分:1)

如果您不想在UserControl中定义属性,您可以随时创建附加依赖项属性,并且可以在公共名称空间下的单独类中声明它。

这样的事情:

MainWindow.xaml

<local:TestUserControl AttachedProperties:ButtonExt.Visibility="Visible" />

TestUserControl.xaml

<Button Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, 
                             Path=(AttachedProperties:ButtonExt.Visibility)}"
        Content="TestButton" />

附属物定义:

public static class ButtonExt
{
    public static readonly DependencyProperty VisibilityProperty;

    public static void SetVisibility(DependencyObject DepObject, Visibility value)
    {
        DepObject.SetValue(VisibilityProperty, value);
    }

    public static Visibility GetVisibility(DependencyObject DepObject)
    {
        return (Visibility)DepObject.GetValue(VisibilityProperty);
    }

    static ButtonExt()
    {
        PropertyMetadata VisibiltyPropertyMetadata = new PropertyMetadata(Visibility.Collapsed);

        VisibilityProperty = DependencyProperty.RegisterAttached("Visibility",
                                                            typeof(Visibility),
                                                            typeof(ButtonExt),
                                                            VisibiltyPropertyMetadata);
    }
}

<强> Some notes about code-behind in MVVM

我同意@dkozl,他的例子没有违反MVVM的原则,在某些情况下,代码存在于View中,例如(个人而言,我总是试图避免代码隐藏):

  • 安装DataContext

  • 使用不同的模式,如Mediator,Proxy等

  • 确定仅与View相关的属性和行为(如您的情况)。

当您使用代码隐藏时最重要的事情是,ViewModel发生了所有可能的操作,即在ViewModel中包含所有逻辑,例如View点击事件,调用ViewModel中的函数。

有关代码隐藏的详细信息,请参阅最近问题的答案:

WPF MVVM Code Behind