【问题标题】:WPF DataBinding Issues - Possible Noob ProblemsWPF 数据绑定问题 - 可能的菜鸟问题
【发布时间】:2013-02-04 17:51:29
【问题描述】:

我正在尝试将 Visibility 类型的 ViewModel 属性绑定到 Dock 面板上的可见性属性:

更新的 ViewModel 代码

public class SelectWaferButtonViewModel : INotifyPropertyChanged
{
    private bool isClicked;

    public SelectWaferButtonViewModel()
    {
        isClicked = false;
    }

    public bool IsControlVisible
    {
        get
        {
            return isClicked;
        }
        set
        {
            isClicked = value;
            OnPropertyChanged("IsControlVisible");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnButtonClick()
    {
        if (isClicked)
        {
            IsControlVisible = false;
        }
        else
        {
            IsControlVisible = true;
        }
    }
    protected virtual void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

这是我更新的 XAML 代码

            <DockPanel
                Name="tvwDockPanel"
                Width="200"
                Visibility="{Binding IsControlVisible, FallbackValue=Collapsed, Converter={StaticResource BoolToVisConverter}}"
                DockPanel.Dock="Left">
                <DockPanel
                    DockPanel.Dock="Top"
                    Height="22">
                </DockPanel>

我在后面的代码中设置了数据上下文:

    tvwDockPanel.DataContext = btnSelectWaferViewModel;

其中 btnSelectWaferViewModel 是这种情况下的 ViewModel 对象。

为了好玩,下面是我的代码

public partial class WaferTrackerWindow : Window
{
    List<ISubscribeEvents> subscriptionList;
    SelectWaferButtonViewModel btnSelectWaferViewModel;

    public WaferTrackerWindow()
    {
        InitializeComponent();

        this.InstantiateObjects();
        this.SubscribeEvents();
        this.SetDataContexts();
    }

    #region Methods

    private void SetDataContexts()
    {
        tvwDockPanel.DataContext = btnSelectWaferViewModel.IsControlVisible;
    }
    private void SubscribeEvents()
    {
        foreach (ISubscribeEvents subscriber in subscriptionList)
        {
            subscriber.SubscribeEvents();
        }
    }
    private void InstantiateObjects()
    {
        btnSelectWaferViewModel = new SelectWaferButtonViewModel();
        subscriptionList = new List<ISubscribeEvents>();
        subscriptionList.Add(
            new Classes.WaferTrackerWindow.SelectWaferButtonView(btnSelectWafer, btnSelectWaferViewModel));
    }

    #endregion
}

我想要做的就是单击按钮 btnSelectWafer 并让 tvwDockPanel 的可见性属性通过绑定设置为可见性。然后,当您再次单击 btnSelectWafer 时,tvwDockPanel 的可见性属性会再次设置回 Collapsed。 tvwDockPanel 的可见性只会是 Collapsed 或 Visible。

任何帮助都会很棒,我对整个数据绑定概念相当陌生。

【问题讨论】:

  • 两个问题,1)你是否在visual studio中启用了绑定跟踪消息(工具->选项->调试->输出窗口),2)有没有发生任何事情或者是否有任何绑定错误在输出窗口中?
  • 您是否在输出窗口中看到任何绑定错误?另外,你能说明你在哪里创建你的视图模型(btnSelectWaferViewModel)吗?
  • Coding Gorilla:我刚刚在输出窗口中启用了绑定错误,以下是我得到的错误:
  • System.Windows.Data 信息:10:无法使用绑定检索值,并且不存在有效的备用值;改用默认值。绑定表达式:路径=可见性;数据项=空;目标元素是'DockPanel'(名称='tvwDockPanel');目标属性是“可见性”(类型“可见性”) System.Windows.Data 信息:10:无法使用绑定检索值,并且不存在有效的后备值;改用默认值。 BindingExpression:(无路径);数据项=空;目标元素是'TreeView'(名称='tvwWaferList');目标属性是“ItemsSource”(类型“IEnumerable”)
  • @user2040460 该错误消息中的关键是:DataItem=null,这意味着它没有绑定到任何实际实例。 btnSelectWaferViewModel 是您的视图模型类的实际实例吗?

标签: c# .net wpf data-binding binding


【解决方案1】:

这里有几个问题:

首先,MVVM 的目的(如果您尝试使用 MVVM 执行此操作)是将逻辑与表示分离。这意味着您的 ViewModel 决不能引用 System.Windows.Controls.ButtonSystem.Windows.VisibilitySystem.Windows 命名空间内的任何其他类。

我不清楚您的 SelectWaferButtonViewModel 类对 Button 做了什么,但您需要从那里删除 Button。

另外,如果您需要从 ViewModel 层操作控件的 Visibility,最好在 XAML 中使用Boolean 属性和BooleanToVisibilityConverter

视图模型:

public bool IsControlVisible {get;set;} //Don't forget INotifyPropertyChanged!!

XAML:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVisConverter"/>
</Window.Resources>
<DockPanel Visibility="{Binding IsControlVisible, Converter={StaticResource BoolToVisConverter}}"/>

【讨论】:

  • 我同意引用Button,但不一定同意Visibility。我可以看到这个论点,但实际上来说,使用转换器只是为了从一种数据类型转换为另一种数据类型是愚蠢的。无论哪种方式,这都不是问题的答案。
  • @CodingGorilla 对不起我的英语不好,你说的箍是什么意思?
  • 顺便说一句,我只是指开销,需要额外的处理等。如果您可以直接绑定到 Visibility 类型的属性,而无需执行转换器中涉及的代码,为什么不直接这样做?
  • @CodingGorilla 是的,我想可以稍微放宽 MVVM 的“限制”,毕竟它只是一个枚举。我猜这完全取决于项目的纯粹程度。
  • 同意,就像我说的我可以看到这个论点,但对我来说它归结为可测试性。这就是 MVVM 中的关键点,构造一个Button 会抑制可测试性,Visibility 不会。
【解决方案2】:

问题是您将 DockPanel 绑定到视图模型的布尔属性,然后将 UI 元素的 Visiblity 属性设置为 datacontext 的 IsControlVisible 属性(这不会存在)。

改为:

private void SetDataContexts()
{
    tvwDockPanel.DataContext = btnSelectWaferViewModel;
}

【讨论】:

    猜你喜欢
    • 2011-03-23
    • 1970-01-01
    • 2011-10-18
    • 2014-05-25
    • 1970-01-01
    相关资源
    最近更新 更多