将 ObservableCollection 绑定到 WPF ListBox

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4138992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:17:18  来源:igfitidea点击:

Binding ObservableCollection to WPF ListBox

wpfwpf-controlsbinding

提问by Flack

I have the below code-behind:

我有以下代码隐藏:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        ObservableCollection<int> sampleData = new ObservableCollection<int>();
        public ObservableCollection<int> SampleData
        {
            get
            {
                if (sampleData.Count <= 0)
                {
                    sampleData.Add(1);
                    sampleData.Add(2);
                    sampleData.Add(3);
                    sampleData.Add(4);
                }
                return sampleData;
            }
        }
    }

My xaml is:

我的 xaml 是:

<Window x:Class="Sandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding Path=SampleData}"/>
    </Grid>
</Window>

The list doesn't display the values in the collection (or anything at all). Can someone point out what my mistake is?

该列表不显示集合中的值(或根本不显示任何值)。有人可以指出我的错误是什么吗?

Do I need to set the DataContext explicitly? I thought if none is set the control will just use itself as the DataContext.

我需要明确设置 DataContext 吗?我想如果没有设置控件将只使用自己作为 DataContext。

回答by Fredrik Hedblad

Yes, you'll need to set the DataContext somehow. It doesn't have a DataContext, because the Window doesn't have a DataContext unless it is set. The ListBox will get the DataContext if you do this in the constructor.

是的,您需要以某种方式设置 DataContext。它没有 DataContext,因为除非设置,否则 Window 没有 DataContext。如果您在构造函数中执行此操作,则 ListBox 将获得 DataContext。

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this;
} 

Otherwise you can use RelativeSource, ElementName etc. in the Binding but I guess you knew that =)

否则,您可以在绑定中使用 RelativeSource、ElementName 等,但我想您知道 =)

回答by ihatemash

I usually pass a viewmodel in on the constructor and set the datacontext to the viewmodel passed in. Then your ObservableCollection can be moved out of the view and put in the viewmodel. This separates your view from your logic and also allows you to unit test the viewmodel code.

我通常在构造函数中传入一个视图模型并将数据上下文设置为传入的视图模型。然后您的 ObservableCollection 可以移出视图并放入视图模型。这将您的视图与逻辑分开,还允许您对视图模型代码进行单元测试。

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel;

    InitializeComponent(); 
} 

回答by jortizromo

Try to use the MvvM patern so in the View you can define the ListBox like this:

尝试使用 MvvM 模式,以便在视图中您可以像这样定义 ListBox:

<ListBox ItemsSource="{Binding Path=Log, UpdateSourceTrigger=PropertyChanged}"/>

Then the View can be without code behind related to the binding source. In the related ViewModel you add something like this:

那么View就可以没有与绑定源相关的代码了。在相关的 ViewModel 中添加如下内容:

public class ViewModel : ViewModelBase
{
    //...
    private ObservableCollection<string> p_Log;

    /// <summary>
    /// A log of a starting process
    /// </summary>
    public ObservableCollection<string> Log
    {
        get { return p_Log; }

        set
        {
            base.RaisePropertyChangingEvent("Log");
            p_Log.Add(value.ToString());
            base.RaisePropertyChangedEvent("Log");
        }
    }
    //....
    /// <summary>
    /// Initializes this view model.
    /// </summary>
    /// <param name="mainWindowViewModel">The view model for this application's main window.</param>
    private void Initialize(MainWindowViewModel mainWindowViewModel)
    {  
        //...
        p_Log = new ObservableCollection<string>();
    }

and then the events defined in ViewModelBase will keep the binding in the View updated, without need of any code behind in the view any time a new string is added to the observable collection p_log.

然后在 ViewModelBase 中定义的事件将保持视图中的绑定更新,而无需在视图中隐藏任何代码,只要将新字符串添加到可观察集合 p_log 中。