为什么我的ObservableCollection没有被观察到?

时间:2014-11-02 08:42:57

标签: c# wpf xaml nlog

我在用户控件中有以下元素,作为默认Grid的唯一子元素:

<ListView ItemsSource="{Binding LogCollection}" Name="LogView">
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn DisplayMemberBinding="{Binding Level}" Header="Level"/>
                <GridViewColumn DisplayMemberBinding="{Binding FormattedMessage}" Width="500" Header="Message"/>
                <GridViewColumn DisplayMemberBinding="{Binding Exception}" Header="Exception"/>
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>

在后面的代码中,我从自定义NLog Target处理以下事件。我只是处理它,因为给了我一个例子,一个完整的WPF菜鸟,但似乎没问题。

private void EventReceived(LogEventInfo message)
{
    Dispatcher.Invoke(() =>
        {
            if (LogCollection.Count >= 50)
            {
                LogCollection.RemoveAt(LogCollection.Count - 1);
            }
            LogCollection.Add(message);
        });
}

事件触发正常,当我单步执行代码时,Add来电就会到达。当我在执行时在XAML视图中鼠标悬停LogCollection时,在Add call, yet my ListView`仍然幸福地意识到它应该向我显示日志事件后,我看到“Count = 1”。

好的,好的,用户控件背后的删节代码是:

public partial class LoggingControl : UserControl
{
    public ObservableCollection<LogEventInfo> LogCollection { get; set; }
    public LoggingControl()
    {
        LogCollection = new ObservableCollection<LogEventInfo>();
        InitializeComponent();

        foreach (Target target in LogManager.Configuration.AllTargets)
        {
            var memoryEventTarget = target as MemoryEventTarget;
            if (memoryEventTarget != null)
            {
                memoryEventTarget.EventReceived += EventReceived;
            }
        }
    }

    private void EventReceived(LogEventInfo message)
    {
        Dispatcher.BeginInvoke(new Action(() =>
                    {
                        LogCollection.Add(message);
                    }));
    }
}

2 个答案:

答案 0 :(得分:1)

正如评论中所提到的,ListView.ItemsSource绑定的绑定上下文似乎是错误的。 DataContext。在您的情况下,手动设置DataContext可以解决问题

this.DataContext = this; 

但是这需要在创建LogCollection之后完成,因为属性本​​身不会引发INotifyPropertyChanged.PropertyChanged事件。

并回答为什么默认情况下DataContext未设置为self是因为DataContext在整个可视树中都是继承的。因此,UserControl与任何其他FrameworkElement一样,默认会从放置它的元素继承其DataContext

另一件值得注意的事情是,只能有一个DataContext值。它将从可视树继承或在UserControl中手动设置。您可以使用继承的上下文,并仍使用UserControlRelativeSource绑定绑定到ElementName属性。

<UserControl ... x:Name="myUserControl">
    <!--  --->
    <ListView ItemsSource="{Binding LogCollection, ElementName=myUserControl}" Name="LogView">

答案 1 :(得分:0)

您确定实际添加项目的LogCollection是您绑定网格的那个吗?我创建了一个示例应用程序,它具有您的代码但按预期工作?也许您需要发布更多代码。

Here is my sample application

也许您的ItemsSource绑定现在正在运行。你在控制台看到任何绑定错误吗?类似于“对象'上找不到”BindingExpression路径错误:'LogCollection'属性的东西“