【问题标题】:Binding an ObservableCollection to ListBox (Easy case?)将 ObservableCollection 绑定到 ListBox(简单案例?)
【发布时间】:2013-10-15 17:14:43
【问题描述】:

真的很难理解绑定。我知道有很多其他线程的标题与这个线程几乎相同,但他们都在尝试做一些比我更复杂的事情,所有的答案都假设一大堆我没有得到的东西: (

我正在尝试显示动态更新的消息日志。我已经定义了一个 Message 类:

public class Message
{
    public DateTime Timestamp { get; private set; }
    public string Value { get; private set; }
    public int Severity { get; private set; }
    public Message(string value, int severity)
    {
        Timestamp = DateTime.Now;
        Value = value;
        Severity = severity;
    }
}

我已经简单地定义了一个 MessageLog 类:

public class MessageLog: ObservableCollection<Message>
{
    public MessageLog(): base()
    { }
}

在我的 MainWindow 构造函数中,我有一个 Log 属性:

public MessageLog Log { get; private set; }

在 MainWindow 构造函数中我初始化 Log:

public MainWindow()
{
    InitializeComponent();
    DataContext = this;
    Log = new Model.MessageLog();
    // and so on
}

在我的主窗口的 XAML 中:

<ListBox Name="MessagePanel" Height="100" ItemsSource="{Binding MessageLog}" IsEnabled="False"/>

现在,如果我将 Message 实例添加到 MessageLog,我希望它们会出现在 ListBox 中。他们没有。我错过了什么?

在此先感谢(如果您能指出我在某个地方清楚地地解释了绑定——尤其是 XAML 对代码的看法以及它可以在哪里寻找东西——那么非常感谢顶部。目前我正在使用 Matthew McDonald 的“C# 中的 Pro WPF 4.5”,但我就是不明白。)

【问题讨论】:

    标签: c# wpf xaml binding observablecollection


    【解决方案1】:

    改变你的构造函数:

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Log = new Model.MessageLog();
    }
    

    到这里:

    public MainWindow()
    {
        InitializeComponent();
        Log = new Model.MessageLog(); // <- This line before setting the DataContext
        DataContext = this;
    }
    

    说明:

    在设置 DataContext 之后设置属性要求您的类实现 INotifyPropertyChanged 并在设置属性后发出更改通知。

    由于您设置属性之前设置了 DataContext,因此在 DataBinding 时,this.Log 的值是 null,并且 WPF 永远不会收到通知它已更改。 p>

    话虽如此,您通常不会将 Data 放在 UI 元素(例如窗口)中。公认和推荐的 WPF 方法是 MVVM,您通常在其中创建一个 ViewModel 并将其设置为 WindowDataContext

    public class MyViewModel
    {
        public MessageLog Log {get;set;}
    
        public MyViewModel()
        {
            Log = new MessageLog();
        }
    }
    

    窗口构造函数:

    public MainWindow
    {
       DataContext = new MyViewModel();
    }
    

    【讨论】:

      【解决方案2】:

      您的集合属性名称是 Log,这是您在ItemsSource 属性中应该绑定的名称;如果您的问题没有打错字,那么您将错误地绑定到MessageLog,并将Binding 更改如下:

      <ListBox Name="MessagePanel" Height="100" ItemsSource="{Binding Log}" IsEnabled="False"/>
      

      有关 WPF (4.5) 中Data Binding 的更多信息和学习,请参阅MSDN Data Binding Overview

      【讨论】:

        【解决方案3】:

        视图的数据上下文必须是视图模型。

        【讨论】:

        • DataContext 只是为 UI 层设置数据层。在关注MVVM design pattern 时,我同意您的观点,即DataContext 应该指向ViewModel。然而,看起来 OP 没有遵循 MVVM,因此在这种情况下,将视图的数据层设置为 w XAML 代码隐藏文件是可以接受的。
        猜你喜欢
        • 2014-09-28
        • 2012-12-16
        • 2018-09-11
        • 2013-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-04
        • 1970-01-01
        相关资源
        最近更新 更多