WPF ObservableCollection未更新视图

时间:2015-11-22 18:31:07

标签: c# wpf observablecollection

这是xaml部分

<ItemsControl x:Name="EventsTop">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Margin="0,1,0,0">
                                <Button Content="{Binding Name}" Template="{DynamicResource ButtonFirst}" Height="50" Margin="15,0,0,0" Padding="10,0,15,0" FontSize="19" FontFamily="/Resources/Fonts/Font Awesome/#FontAwesome" BorderThickness="5,0,0,0" BorderBrush="#8CC152" Background="#2980B9" HorizontalContentAlignment="Left" Foreground="Black" Click="TabOpen" Tag="{Binding Id}"></Button>
                                <StackPanel Background="#2980B9" Margin="15,0,0,5" Visibility="Collapsed" AllowDrop="True" Tag="{Binding Id}" Drop="RowDrop">
                                    <Border BorderThickness="5,0,0,0" BorderBrush="#8CC152">
                                        <StackPanel>
                                            <DockPanel LastChildFill="False">
                                                <Label DockPanel.Dock="Left" Width="140" Content="Date" FontSize="19" BorderThickness="0,0,0,1"   FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
                                                <Label DockPanel.Dock="Left" Width="190" Content="Event"  FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
                                                <Label DockPanel.Dock="Left" Width="100" Content="Select" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
                                            </DockPanel>
                                            <ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="150">
                                                <ItemsControl ItemsSource="{Binding Details}">
                                                    <ItemsControl.ItemTemplate>
                                                        <DataTemplate>
                                                            <DockPanel LastChildFill="False">
                                                                <Label Content="{Binding Date}" DockPanel.Dock="Left" Width="140" FontSize="19" BorderThickness="0" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
                                                                <Label Content="{Binding EventName}" DockPanel.Dock="Left" Width="165" FontSize="19" BorderThickness="0" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
                                                                <Border Width="97">
                                                                    <CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding Checked}"></CheckBox>
                                                                </Border>
                                                                <Button Width="25" DockPanel.Dock="Left" Content="&#xf08d;" BorderThickness="0" Background="Transparent"  FontFamily="/Resources/Fonts/Font Awesome/#FontAwesome"></Button>
                                                            </DockPanel>
                                                        </DataTemplate>
                                                    </ItemsControl.ItemTemplate>
                                                </ItemsControl>
                                            </ScrollViewer>
                                        </StackPanel>
                                    </Border>
                                </StackPanel>
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

这是xaml.cs

 private void WindowLoaded(object sender, RoutedEventArgs e)
    {
        EventHelper eventHelper = new EventHelper();

        TopEvents = eventHelper.GetSports(EventHelper.EventGroup.Top);
        foreach (Sport item in TopEvents)
        {
            item.Name = "\uf196 " + item.Name;
        }
        EventsTop.ItemsSource = TopEvents;

        AllEvents = eventHelper.GetSports(EventHelper.EventGroup.All);
        foreach (Sport item in AllEvents)
        {
            item.Name = "\uf196 " + item.Name;
        }
        EventsAll.ItemsSource = AllEvents;

        Sport.ItemsSource = eventHelper.GetSports(EventHelper.EventGroup.All);
    }

    private void RowMouseDown(object sender, MouseButtonEventArgs e)
    {
        DockPanel currentRow = (DockPanel) sender;
        int rowOffset = Convert.ToInt32(currentRow.Tag);
        DragDrop.DoDragDrop(currentRow,rowOffset,DragDropEffects.Copy);
    }

    private void RowDrop(object sender, DragEventArgs e)
    {
        int rowOffset = (int) e.Data.GetData(typeof (int));
        AllEvents[0].Name = "1";
    }

我的收集模型

class Sport : INotifyPropertyChanged
{
    private int _id;
    private string _name = string.Empty;
    private ObservableCollection<Details> _details = new ObservableCollection<Details>();

    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            NotifyPropertyChanged("Content");
        }
    }

    public ObservableCollection<Details> Details
    {
        get { return _details; }
        set { _details = value; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
            MessageBox.Show(info);
        }
    }
}

因此,当我更改属性时,它会抛出MessageBox但不会更新GUI。

我是xaml.cs我正在调用GetEvents方法 return ObservableCollection

我想更改位于Name

Sport中的ObservableCollaction<Sport> AllEvents

您可以在xaml.cs中的RowDrop方法中看到它 在调试中,我注意到AllEvents[0].Name已更改,但视图未更新

更新

ObservabelCollection声明的一部分

public MainPage()
    {
        InitializeComponent();
        AllEvents = new ObservableCollection<Sport>();
        TopEvents = new ObservableCollection<Sport>();
        EventsTop.ItemsSource = TopEvents;
        EventsAll.ItemsSource = AllEvents;
    }

    private ObservableCollection<Sport> AllEvents;
    private ObservableCollection<Sport> TopEvents;

更新第二次 当我使用窗口激活事件时,我发现它正在工作

4 个答案:

答案 0 :(得分:2)

将名为property的问题传递给NotifyPropertyChanged方法。参数名称应为属性名称。请将Name属性更改为

public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }

答案 1 :(得分:1)

我找到了解决方案。

所以,ObservableCollection工作得非常好,但需要刷新 出现在视图中,我们需要使用

CollectionViewSource.GetDefaultView(ObservableCollection).Refresh() 方法

我认为这会对某人有所帮助

答案 2 :(得分:0)

使用CallerMemberNameAttribute以避免必须使名称正确并允许重构:

public IEnumerable<Details> Details //note IEnumerable, no calling code needs to know its concrete type
{
    get { return _details; }
    set
    {
        _details = value;
        NotifyPropertyChanged();
    }
}

每个属性设置者都应该通知属性更改,所以:

private readonly ObservableRangeCollection<Details> _details = new ObservableRangeCollection<Details>();

public IEnumerable<Details> Details
{
    get { return _details; }
    set { _details.Replace(value); }
}

使用observable range collection你可以这样做:

using System;
using System.Reactive.Subjects;

namespace ConsoleApplication17
{
    internal interface ILogger
    {
        void Log(String message);
    }

    internal class Logger : ILogger
    {
        private readonly Subject<String> _logMessagesObservable = new Subject<string>();

        public void Log(string json)
        {
            _logMessagesObservable.OnNext(json);
        }

        public IObservable<String> LogMessagesObservable { get { return _logMessagesObservable; } }
    }

    internal class ConsoleLogListener
    {
        public ConsoleLogListener(IObservable<String> messages)
        {
            messages.Subscribe(Console.WriteLine);
        }
    }

    internal class WindowsEventListener
    {
        public WindowsEventListener(IObservable<String> messages)
        {
            messages.Subscribe(WriteToEventLog);
        }

        private void WriteToEventLog(String message)
        {
            //Write to event log
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Logger logger = new Logger();

            //Link up any subscribers
            new ConsoleLogListener(logger.LogMessagesObservable);
            new WindowsEventListener(logger.LogMessagesObservable);
            //... more listeners go here.           

            DoSomeWork(logger);
        }

        private static void DoSomeWork(ILogger logger)
        {
            logger.Log("Something interesting");
            logger.Log("Something else interesting");
        }
    }
}

答案 3 :(得分:0)

来自MSDN

  

在添加,删除,更改,移动项目或整个项目时发生   列表刷新。

更改并不意味着更改子属性,而是更改任何索引处的项目。

因此,当您修改集合项时,您需要通知绑定该属性已更改。在修改集合中的项目后,从窗口的viewmodel中,您将通知集合已更改。

NotifyPropertyChanged("AllEvents");