【问题标题】:WPF UserControls: Have a Command that is only available internally in the UserControlWPF UserControls:有一个仅在 UserControl 内部可用的命令
【发布时间】:2015-11-30 13:40:11
【问题描述】:

我正在做一个 WPF UserControl

在这个 UserControl 内部,我有几个 Button 可以在特定条件下使用,因此将它们绑定到命令是完美的。

这些按钮调用的命令不应该在用户控件之外可用。

如果我将我的命令设为私有,UserControl 的 XAML 表示他想要公共成员。

那么,怎样才能让一个 UserControl 内部有多个命令,但在 UserControl 之外不可用?

例子:

<Wizard CanGoPrevious="{Binding SomeViewModelProperty}">
    <WizardPage>
        <TextBlock>Page one</TextBlock>
    </WizardPage>
</Wizard>

向导的 XAML:

<DockPanel DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type wizard:Wizard}}}" LastChildFill="True">
    <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" HorizontalAlignment="Right"> 
        <Button Content="{Binding PreviousButtonText}" Command="{Binding GoToPreviousPageCommand}"/>
    </StackPanel>
    <ContentControl ></ContentControl>
</DockPanel>

背后的向导代码:

//Protected doesn't work. Also, this command should not be available outside of the Wizard `UserControl`
protected DelegateCommand GoToPreviousPageCommand { get; set; } 

在构造函数中是这样赋值的

GoToPreviousPageCommand = new DelegateCommand(GoToPreviousPage, CanGoToPreviousPage);


    private void GoToPreviousPage()
    {
        //[...]
    }

    private bool CanGoToNextPage()
    {
        //Some usage of the Wizard's DP:
        return CanGoPrevious //&& some other stuff
    }

【问题讨论】:

  • 别打扰了。它是一个用户控件——在代码隐藏中包含与 UI 有关的逻辑非常好。
  • @Will 好的,但是找不到为 UserControl 提供对必须仅在内部可用的命令的公共访问权限。

标签: wpf xaml mvvm user-controls command


【解决方案1】:

编辑:添加示例代码(应该能够复制/过去/运行): 将命令保留为公开,但将您的 ViewModel 设为内部将使命令对外部代码不可见!

<Window x:Class="InternalCommandUsageSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:InternalCommandUsageSample"
    Title="MainWindow" Height="350" Width="525">
<local:MyUserControl/>

测试用户控件的窗口后面的代码:

using System.Windows;

namespace InternalCommandUsageSample
{
public partial class MainWindow : Window
{
    public MainWindow()
    {
        var vm = new MyViewModel();
        DataContext = vm;

        InitializeComponent();
    }
}

}

用户控制:

<UserControl x:Class="InternalCommandUsageSample.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
    <TextBlock Text="{Binding Message, Mode=OneWay}"/>
    <Button Content="Test Me" Command="{Binding TestMeCommand}"/>
</StackPanel>

以及在您的程序集之外不可见的内部视图模型:

internal class MyViewModel : INotifyPropertyChanged
{
    private string _message = "click the button";
    private DelegateCommand _cmd;

    public DelegateCommand TestMeCommand
    {
        get
        {
            return _cmd ?? (_cmd = new DelegateCommand(cmd => { Message = "Your button click envoked an internal command"; }));
        }
    }

    public string Message
    {
        get { return _message; }
        set
        {
            if (_message != value)
            {
                _message = value;
                OnPropertyChanged("Message");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

编辑:在 cmets 中询问了关于如何使用 suer 控件和视图模型的依赖属性的附加问题。方法有很多,这是其中之一:

        public string MySampleDependencyProperty
    {
        get { return (string)GetValue(MySampleDependencyPropertyProperty); }
        set { SetValue(MySampleDependencyPropertyProperty, value); }
    }

    public static readonly DependencyProperty MySampleDependencyPropertyProperty = 
        DependencyProperty.Register("MySampleDependencyProperty", typeof(string), 
        typeof(MyUserControl),
        new FrameworkPropertyMetadata("", 
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (o, e) => ((MyUserControl)o).OnMySampleDependencyPropertyChanged()));

    private void OnMySampleDependencyPropertyChanged()
    {
        viewMdoel.WhateverProperty = MySampleDependencyProperty;
    }

【讨论】:

  • 好的,这意味着可以在库中进行编辑,但可以接受。最初我想创建一个 ViewModel,但我没有感觉到 DependencyProperties 可以实现,我错了吗?
  • 贴一些你的代码,这样我就可以看到你在说什么。因为使用 ViewModel 您不需要依赖属性,所以只要它们引发 propertyChanged 事件,您就可以拥有常规属性。一个命令也可以(或通常)有一个私有的设置器,所以它是不可编辑的。
  • 你想看代码的哪一部分?问题是在我们将使用这个UserControl 的窗口中,一些属性(UserControl)将绑定到 MainWindow 的 ViewModel 的属性。在我的 UserControl 中,我需要这些绑定值的一些值
  • 我添加了一些代码。另外,我尝试将命令设置为内部命令,但 Visual Studio 似乎仍然不满意。 VS 告诉我它应该是一个公共成员,如果我启动它,我得到一个 BindingExpression 路径错误
  • 我会在这里输入一些东西
猜你喜欢
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 2010-11-22
  • 2012-06-27
  • 1970-01-01
相关资源
最近更新 更多