为什么我的ObservableCollection没有被注意到

本文关键字:注意到 我的 ObservableCollection 为什么 | 更新日期: 2023-09-27 18:28:50

我在用户控件中有以下元素,作为默认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 noob,但它似乎还可以

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

为什么我的ObservableCollection没有被注意到

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

this.DataContext = this; 

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

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

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

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

您确定实际添加项目的LogCollection就是您将网格绑定到的那个吗?我已经创建了一个示例应用程序,该应用程序包含您的代码,但工作正常?也许你需要发布更多的代码。

这是我的应用程序示例。

也许您的ItemsSource绑定现在正在工作。您在控制台中看到任何绑定错误吗?类似于"BindingExpression路径错误:在'object'上找不到'LogCollection'属性"