无法将 ItemsControl 绑定到 ObservableCollection
Cannot bind ItemsControl to ObserveableCollection
如标题所述,我在将 ObservableCollection
绑定到 ItemsControl
时遇到问题。
MainWindow.xaml:
xmlns:ext="clr-namespace:DeConfigurator.Classes"
...
<ItemsControl ItemsSource="{Binding Source=ext:InAppSink.Logs}" Name="LogList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Level}">
<TextBlock TextWrapping="Wrap">
<TextBlock.Text>
<Binding Path="FormattedEntry" />
</TextBlock.Text>
</TextBlock>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
InAppSink:
namespace DeConfigurator.Classes
{
public class InAppSink : ILogEventSink
{
static readonly int MAX_ITEMS = 200;
static readonly int TO_REMOVE = 50;
public ObservableCollection<LogItem> Logs { get; set; } = new ObservableCollection<LogItem>();
public void Emit(LogEvent logEvent)
{
if (logEvent == null){throw new ArgumentNullException(nameof(logEvent)); }
if(Logs.Count > MAX_ITEMS)
{
for(int i = 0; i < TO_REMOVE; ++i)
{
Logs.RemoveAt(i);
}
}
Logs.Add(new LogItem(logEvent));
}
}
public class LogItem
{
readonly ITextFormatter _textFormatter =
new MessageTemplateTextFormatter(
"{Timestamp:yyyy-MM-dd HH:mm:ss zzz} [{Level}] [{Method}] {Message:lj}{NewLine}{Properties:j}{NewLine}{Exception}"
);
public string FormattedEntry { get; set; }
public string Level { get; set; }
public DateTime LogDate { get; set; }
public LogItem(LogEvent logEvent)
{
var renderSpace = new StringWriter();
_textFormatter.Format(logEvent, renderSpace);
FormattedEntry = renderSpace.ToString();
Level = logEvent.Level.ToString();
LogDate = logEvent.Timestamp.DateTime;
}
}
}
我想要的结果是让每个日志条目显示为折叠的扩展器,级别和日期作为 header,格式化的日志条目作为放置时的文本内容。我得到的是文本“ext:InAppSink.Logs”中的每个字符用于创建扩展器 objects。为什么这个绑定不起作用?
为了绑定到对象的 属性,您必须将绑定的 Path
设置为源 属性 的名称,而源对象通常是通过 Binding 的目标对象的 DataContext
传递。
有关详细信息,请参阅 Microsoft 文档中的 Data binding overview。
所以替换
ItemsSource="{Binding Source=ext:InAppSink.Logs}"
和
ItemsSource="{Binding Path=Logs}"
并将 InAppSink class 的实例分配给视图的 DataContext,例如在 MainWindow 构造函数中:
private readonly InAppSink sink = new InAppSink();
public MainWindow()
{
InitializeComponent();
DataContext = sink;
}
Logs
属性 也应该是只读的,比如
public ObservableCollection<LogItem> Logs { get; } = new ObservableCollection<LogItem>();
或发出更改通知。
如标题所述,我在将 ObservableCollection
绑定到 ItemsControl
时遇到问题。
MainWindow.xaml:
xmlns:ext="clr-namespace:DeConfigurator.Classes"
...
<ItemsControl ItemsSource="{Binding Source=ext:InAppSink.Logs}" Name="LogList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Level}">
<TextBlock TextWrapping="Wrap">
<TextBlock.Text>
<Binding Path="FormattedEntry" />
</TextBlock.Text>
</TextBlock>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
InAppSink:
namespace DeConfigurator.Classes
{
public class InAppSink : ILogEventSink
{
static readonly int MAX_ITEMS = 200;
static readonly int TO_REMOVE = 50;
public ObservableCollection<LogItem> Logs { get; set; } = new ObservableCollection<LogItem>();
public void Emit(LogEvent logEvent)
{
if (logEvent == null){throw new ArgumentNullException(nameof(logEvent)); }
if(Logs.Count > MAX_ITEMS)
{
for(int i = 0; i < TO_REMOVE; ++i)
{
Logs.RemoveAt(i);
}
}
Logs.Add(new LogItem(logEvent));
}
}
public class LogItem
{
readonly ITextFormatter _textFormatter =
new MessageTemplateTextFormatter(
"{Timestamp:yyyy-MM-dd HH:mm:ss zzz} [{Level}] [{Method}] {Message:lj}{NewLine}{Properties:j}{NewLine}{Exception}"
);
public string FormattedEntry { get; set; }
public string Level { get; set; }
public DateTime LogDate { get; set; }
public LogItem(LogEvent logEvent)
{
var renderSpace = new StringWriter();
_textFormatter.Format(logEvent, renderSpace);
FormattedEntry = renderSpace.ToString();
Level = logEvent.Level.ToString();
LogDate = logEvent.Timestamp.DateTime;
}
}
}
我想要的结果是让每个日志条目显示为折叠的扩展器,级别和日期作为 header,格式化的日志条目作为放置时的文本内容。我得到的是文本“ext:InAppSink.Logs”中的每个字符用于创建扩展器 objects。为什么这个绑定不起作用?
为了绑定到对象的 属性,您必须将绑定的 Path
设置为源 属性 的名称,而源对象通常是通过 Binding 的目标对象的 DataContext
传递。
有关详细信息,请参阅 Microsoft 文档中的 Data binding overview。
所以替换
ItemsSource="{Binding Source=ext:InAppSink.Logs}"
和
ItemsSource="{Binding Path=Logs}"
并将 InAppSink class 的实例分配给视图的 DataContext,例如在 MainWindow 构造函数中:
private readonly InAppSink sink = new InAppSink();
public MainWindow()
{
InitializeComponent();
DataContext = sink;
}
Logs
属性 也应该是只读的,比如
public ObservableCollection<LogItem> Logs { get; } = new ObservableCollection<LogItem>();
或发出更改通知。