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

6

我有一个自定义控件,其中包含一个按钮:

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

<这里设置加载按钮的可见性>表示我想要设置控件的可见性。如何在不破坏MVVM模式的情况下完成?

感谢您的时间。


你可以在你的UserControl中创建一个DependencyProperty,并将其内部绑定到Button的可见性。 - dkozl
你想根据什么条件设置按钮的可见性? - yo chauhan
基本上,我想能够在窗口中嵌入此控件和关联的ViewModel(包括按钮)或控件中排除按钮。这可以在设计时设置。如果要在运行时执行此操作,我会有机会,因为我以前做过这个 - 但是,我从未从另一个控件设置控件的一个组件的可见性... - MoonKnight
@dkozl,你能提供一个小例子吗?我不明白如何在UserControl中创建一个dp。谢谢你的时间... - MoonKnight
3个回答

5
你可以在你的UserControl中创建DependencyProperty:
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


这个必须放在控件代码后面吗?我试图严格不让任何东西出现在代码后面。非常感谢您的时间... - MoonKnight
1
你不需要在代码中操作视图。它只是另一个“DependencyProperty”,就像“UserControl.Visibility”一样,通过它你可以控制“Button”的可见性。所有的东西仍然由你的ViewModel控制,所以你不会破坏MVVM模式。 - dkozl

2

您好,只需在UserControl1中创建一个bool或Visibility类型属性,并在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>


1
非常感谢您在这里花费时间... 然而,这会破坏MVVM模式,因为它将视图与其代码绑定在一起... - MoonKnight

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);
    }
}

MVVM中代码后台的一些注意事项

我同意@dkozl的观点,他的例子并没有违反MVVM原则,在某些情况下,代码存在于View中,例如(个人而言,我总是尽量避免使用代码后台):

  • 安装DataContext

  • 使用不同的模式,如中介者、代理等。

  • 确定仅适用于View的属性和行为(如您的情况所示)。

当您使用代码后台时,最重要的是所有可以通过ViewModel进行的操作都要发生,即在ViewModel中包含所有逻辑,并且例如,在View的点击事件中,调用在ViewModel中的函数。

有关代码后台的更多信息,请参见最近问题的答案:

WPF MVVM Code Behind


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接