WPF MVVM更新列表框

时间:2016-01-22 11:37:04

标签: c# wpf xaml mvvm listbox

问题

当用户选择某些数据时,我正在尝试更新 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; }
}

4 个答案:

答案 0 :(得分:0)

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

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>();

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

答案 1 :(得分:0)

尝试使用xhtml:

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

也许还可以添加Mode = TwoWay

编辑:

为什么要刷新ListBox并创建一个新的ObservableCollection?

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

答案 2 :(得分:0)

我认为你已经错误地实现了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}"

答案 3 :(得分:0)

一次创建一个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);
         }
    }
}