【问题标题】:How main window can catch the NotifyPropertyChanged event of a property in its contained Usercontrol主窗口如何在其包含的用户控件中捕获属性的 NotifyPropertyChanged 事件
【发布时间】:2013-01-15 09:10:45
【问题描述】:

我有一个 UserControl,它包含布尔属性 A。 在包含该 UserControl 的主窗口中,我必须启用/禁用按钮取决于 A 的值。 我试图将 A 设为公共和绑定按钮,如下所示:

<Button IsEnabled="{Binding MyUserControl.A}"/>

在 UserControl 中,我为 Property A 设置了 PropertyChangedEventHandler,如下所示:

private bool _a;
public bool A
{
    get
    {
         return _a;
    }
         set
    {
         if (_a == value)
             return
         _a = value;
         OnPropertyChanged("A");
    }
}

看起来不错。但我不知道为什么它不起作用。 似乎我缺乏一些实现来在主窗口与其用户控件之间进行通信(因为使用 OnPropertyChanged,用户控件内的所有绑定都可以正常工作)。

我有一些解决方案是 1.使用Messenger从Usercontrol发送消息,内容为A,主控件将捕获并设置按钮的IsEnabled值。 2. 创建一个事件并在 A 的值发生变化时引发它。

您对这个问题以及如何解决它有任何想法吗? 您认为以下 2 种解决方案效果如何,或者您有其他建议吗?

感谢阅读。

> 这个问题解决了。在代码隐藏中设置用户控件的数据上下文时是我的错误,并且不承认我已经在数据模板中设置了它们。 --> 所以,复制使用户控件的视图模型初始化了 2 次。 --> 不知何故,它使 NotifyPropertyChange 无法正常工作。

对不起,这个问题的标题不适合这个愚蠢的错误。看来我采取了正确的方法来解决标题问题。 感谢您的阅读和建议。

【问题讨论】:

  • 您是否尝试将您的A 属性定义为依赖属性?
  • 绑定有效吗?您可以设置跟踪级别 (IsEnabled="{Binding MyUserControl.A, PresentationTraceSources.TraceLevel=High}") 以检查绑定是否有效
  • @Alexander Balte:对不起,你能解释一下吗?
  • @rhe1980:是的,绑定效果很好,我没有发现与输出窗口绑定相关的错误。
  • @kidgu:您的用户控件(MyUserControl)在哪里实例化?在 xaml 中还是在后面的代码中?我试过了,效果很好。

标签: c# .net wpf mvvm


【解决方案1】:

在 wpf 中显示用户控件的另一种方法。检查此 StackOverflow 讨论 here

INotifyPropertyChanged 的​​替代:绑定的依赖属性。

//用户控制

public partial class UserControl1 : UserControl
{
   public bool A
    {
        get { return (bool)GetValue(AProperty); }
        set { SetValue(AProperty, value); }
    }

    public static readonly DependencyProperty AProperty =
        DependencyProperty.Register("A", typeof(bool), typeof(UserControl1), new UIPropertyMetadata(false));

    public UserControl1()
    {
        InitializeComponent();
        DataContext = this;
    }
}

}

//主窗口.xaml

 <Window x:Class="WpfApplication1.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:src="clr-namespace:WpfApplication1"
      Height="300" Width="300">
    <StackPanel>
      <src:UserControl1 x:Name="myControl" />
      <Button IsEnabled="{Binding A, ElementName=myControl}" />
    </StackPanel>

【讨论】:

    【解决方案2】:

    绑定表达式始终使用DataContext 作为评估绑定路径的基础。因此,在您的情况下,DataContext 必须是窗口本身,您可以在代码隐藏文件的窗口构造函数中设置它:

    this.DataContext = this;
    

    另请注意,要使您的窗口正常工作,您需要有一个名为 MyUserControl 的属性。

    另一种选择是为您可能在 XAML 中实例化的 MyUserControl 实例命名,然后在绑定表达式中使用 ElementName

    <Grid>
        <loc:MyUserControl Name="myUserControl" />
        <Button IsEnabled="{Binding A, ElementName=myUserControl}" />
    </Grid>
    

    【讨论】:

    • 我必须将 datacontext 设置为 windows 的视图模型(我正在使用 mvvm)。我也尝试使用 ElementName & Path 而不是使用 myUserControl.A,但出现了同样的现象(没有绑定错误,但是当我更改 A 的值时没有任何反应)
    【解决方案3】:

    您需要通过在资源中声明它来创建 UserControl 的实例并将其设置为 datacontext ,然后您才能使用它。试试这个。

    <Window.Resources>
        <WpfApplication2:UserControl1 x:Key="MyUserControl"/>
    </Window.Resources>
    
    <StackPanel DataContext="{StaticResource MyUserControl}">
        <Button IsEnabled="{Binding Path=A}" Content="Test" Height="20" />
    </StackPanel>
    

    【讨论】:

    • 我在视图模型中初始化了这个用户控件。我刚刚添加了其他信息。希望更清楚!感谢您的评论!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多