WPF MVVM更新列表框

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF MVVM更新列表框相关的知识,希望对你有一定的参考价值。

问题


当用户选择某些数据时,我正在尝试更新ListBox中的值。由于某种原因,ListBox不会更新实时,我必须关闭应用程序并重新打开以显示数据。

我已经将模式更改为MVVM,因为人们已经说过这样更容易使用。


在我的表单上,我设置了DataContext:

public Live()
{
    LiveMainViewModel graphUpdater = new LiveMainViewModel();
    this.DataContext = graphUpdater;
}

在我的ViewModel构造函数中,我调用了一个刷新:

public LiveMainViewModel()
{
    RefreshListBox();
}

我在附加OnPropertyChanged事件时设置了一个Property:

public ObservableCollection<ITimeLineDataItem> SlideDataItems { 
    get { return _slideDataItems; }
    set
    {
        _slideDataItems = value;
        OnPropertyChanged("SlideDataItems");
    }
}
private ObservableCollection<ITimeLineDataItem> _slideDataItems;

在我的刷新方法中,我将新项目添加到列表中:

public void RefreshListbox()
{
    _slideDataItems = new ObservableCollection<ITimeLineDataItem>();

    foreach (podiaPublish.Marker pMarker in Global.gChapter.MarkerList)
    {
        if (pContent.Markup.Contains(".png"))
        {
             var brush = new ImageBrush(bitmapSource);

             var lb1 = new TempDataType()
             {
                 Name = pContent.Markup,
                 BackgroundImage = brush
             };

             _slideDataItems.Add(lb1);
         }
    }
}

摘要


因此,当我实时添加项目时,ListBox不会随数据一起更新,但是当我重新加载应用程序时,数据将会出现。


如何使用用户添加的数据更新ListBox?

编辑


输出窗口:

System.Windows.Data Warning: 56 : Created BindingExpression (hash=10555762) for Binding (hash=14988671)
System.Windows.Data Warning: 58 :   Path: 'SlideDataItems'
System.Windows.Data Warning: 60 : BindingExpression (hash=10555762): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=10555762): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=10555762): Attach     to System.Windows.Controls.ListBox.ItemsSource (hash=30133081)
System.Windows.Data Warning: 67 : BindingExpression (hash=10555762): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=10555762): Found data context element: ListBox (hash=30133081) (OK)
System.Windows.Data Warning: 71 : BindingExpression (hash=10555762): DataContext is null
System.Windows.Data Warning: 65 : BindingExpression (hash=10555762): Resolve source deferred

我如何绑定:

<ListBox x:Name="ListSrc" Background="#ececec" ItemsSource="{Binding SlideDataItems}" dd:DragDrop.IsDragSource="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderBrush="Transparent" BorderThickness="0">

我的自定义类:

public interface ITimeLineDataItem
{
    TimeSpan? StartTime { get; set; }
    TimeSpan? EndTime { get; set; }
    Boolean TimelineViewExpanded { get; set; }
}
答案

这是因为您将绑定对象更改为另一个但不通知您的绑定。在这种情况下,您可以用下一个替换您的代码:

public void RefreshListbox()
{
    var slideDataItems = new ObservableCollection<ITimeLineDataItem>();

    foreach (podiaPublish.Marker pMarker in Global.gChapter.MarkerList)
    {
        if (pContent.Markup.Contains(".png"))
        {
             var brush = new ImageBrush(bitmapSource);

             var lb1 = new TempDataType()
             {
                 Name = pContent.Markup,
                 BackgroundImage = brush
             };

             slideDataItems.Add(lb1);
         }
    }

    SlideDataItems = slideDataItems;
}

在这种情况下,您可以使用属性的通知更改对象。将触发数据目标(ListBox)并更新其针对新数据源的表示。

另一种方法是通过切换来改变现有的数据源

_slideDataItems = new ObservableCollection<ITimeLineDataItem>();

到了

_slideDataItems.Clear();

并在其声明中初始化字段:

private ObservableCollection<ITimeLineDataItem> _slideDataItems = new ObservableCollection<ITimeLineDataItem>();

现在,您将始终拥有一个数据源对象,并可以通过添加新元素,删除元素或清除所有集合来更新它。

另一答案

我认为你已经实现了错误的ObservableCollection。 ITimeLineDataItem的属性应该实现INotifyPropertyChanged而不是集合。

public class MyCollection : ObservableCollection<ITimeLineDataItem>
{
}

public class ITimeLineDataItem: INotifyPropertyChanged
{
    private string _aProperty;
    public string  AProperty
    {
        get { return _aProperty; }
        set
        {
            if (_aProperty!= value)
            {
                _aProperty= value;
                OnPropertyChanged("AProperty");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

然后在您的视图模型(也将是您的数据上下文)中,您将拥有:

MyCollection<ITimeLineDataItem> SlideDataItems {get; set;}

SlideDataItems  = MyCollection<ITimeLineDataItem>();

最后你需要在你的xaml中设置

ItemsSource="{Binding SlideDataItems}"
另一答案

试试xhtml

ItemsSource="{Binding SlideDataItems, UpdateSourceTrigger=PropertyChanged}"

也许还可以添加Mode = TwoWay

编辑:

你为什么要刷新列表框并创建一个新的ObservableCollection?

尝试在最后的方法OnPropertyChanged("SlideDataItems");中触发RefreshListbox()

另一答案

创建一个ObservableCollection,然后在Refresh方法中清除它。

public ObservableCollection<ITimeLineDataItem> SlideDataItems { 
    get { return _slideDataItems; }
    set
    {
        _slideDataItems = value;
        OnPropertyChanged("SlideDataItems");
    }
}
private ObservableCollection<ITimeLineDataItem> _slideDataItems = new ObservableCollection<ITimeLineDataItem>();

在Refresh方法中,清除ObservableCollection,但不要重新创建它。

public void RefreshListbox()
{
    SlideDataItems.Clear();

    foreach (podiaPublish.Marker pMarker in Global.gChapter.MarkerList)
    {
        if (pContent.Markup.Contains(".png"))
        {
             var brush = new ImageBrush(bitmapSource);

             var lb1 = new TempDataType()
             {
                 Name = pContent.Markup,
                 BackgroundImage = brush
             };

             _slideDataItems.Add(lb1);
         }
    }
}

以上是关于WPF MVVM更新列表框的主要内容,如果未能解决你的问题,请参考以下文章

WPF MVVM C#:列表框拖放而没有代码

选定的 WPF 列表框绑定仅更新视图中的项目

ItemsControl 组合框 selecteditem C# WPF MVVM

MVVM WPF:为啥在运行应用程序时更新文本框中的文本后模型中的属性始终为空?

DataGridTemplateColumn 绑定在 WPF 中使用文本框和 MVVM

WPF MVVM:组合框 SelectedValue 绑定