我一直在敲桌子试图找出为什么我继续得到这个WPF XAML数据绑定错误。
System.Windows.Data错误:40:BindingExpression路径错误:在'object'''TreeViewItem'(Name ='')'上找不到'Source'属性。空值 System.Windows.Data错误:40:BindingExpression路径错误:'对象'''TreeViewItem'(Name ='')'上找不到'Source'属性。空
我已将其追溯到XAML代码中的这一行
<local:GameLogSourceTree x:Name="_gamesSourcesTree" TreeNodeStyle="{StaticResource GenericFolders}" TreeStyle="{StaticResource GenericTreeStyle}" NodeSortDescriptions="{StaticResource AscendingNames}"/>
指的是xaml代码DataTriggers中的“Source”属性,如果这是正确的。任何帮助都很受欢迎。
以下是XAML代码&amp;它背后的C#代码
XAML Code
<UserControl x:Class="Test.UI.Noc"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:Test.UI"
xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:Logs="clr-namespace:Test.Logs;assembly=Test.Logs">
<UserControl.Resources>
<local:SourceStateConverter x:Key="gamesourceStateConverter"/>
<DataTemplate x:Key="GameNodeTemplate" DataType="{x:Type local:GameLogSourceNode}">
<StackPanel x:Name="GroupPanel" Orientation="Horizontal" Margin="0,2,0,2">
<Image x:Name="Folder" Source="/Test.UI;component/Test.UI/Images/GameRoot.png"/>
<TextBlock x:Name="CategoryName" Margin="2,0,0,0" Text="{Binding Path=Source.(Logs:IGameLogsSource.Name)}"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Value="True" Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}}">
<Setter TargetName="CategoryName" Property="TextBlock.FontWeight" Value="Bold"/>
<Setter Property="UIElement.Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="2" BlurRadius="10" RenderingBias="Quality"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Value="-1" Binding="{Binding Path=Source, Converter={StaticResource gamesourceStateConverter}}">
<Setter TargetName="Folder" Property="Image.Source" Value="/Test.UI;component/Test.UI/Images/Process.png"/>
</DataTrigger>
<DataTrigger Value="0" Binding="{Binding Path=Source, Converter={StaticResource gamesourceStateConverter}}">
<Setter TargetName="Folder" Property="Image.Source" Value="/Test.UI;component/Test.UI/Images/Process.png"/>
</DataTrigger>
<DataTrigger Value="1" Binding="{Binding Path=Source, Converter={StaticResource gamesourceStateConverter}}">
<Setter TargetName="Folder" Property="Image.Source"
Value="/Test.UI;component/Test.UI/Images/GameStopping.png"/>
</DataTrigger>
<DataTrigger Value="2" Binding="{Binding Path=Source, Converter={StaticResource gamesourceStateConverter}}">
<Setter TargetName="Folder" Property="Image.Source"
Value="/Test.UI;component/Test.UI/Images/GameStopped.png"/>
</DataTrigger>
<DataTrigger Value="Games" Binding="{Binding Path=Source.(Logs:IGameLogsSource.Name)}">
<Setter TargetName="Folder" Property="Image.Source"
Value="/Test.UI;component/Test.UI/Images/GameRoot.png"/>
</DataTrigger>
<DataTrigger Value="Common" Binding="{Binding Path=Source.(Logs:IGameLogsSource.Name)}">
<Setter TargetName="Folder" Property="Image.Source"
Value="/Test.UI;component/Test.UI/Images/NocRoot.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Style x:Key="GenericFolders" TargetType="{x:Type TreeViewItem}">
<Style.Resources>
<Brush x:Key="{x:Static SystemColors.HighlightBrushKey}">Transparent</Brush>
<Brush x:Key="{x:Static SystemColors.ControlBrushKey}">Transparent</Brush>
<Brush x:Key="{x:Static SystemColors.ControlTextColorKey}">Black</Brush>
</Style.Resources>
<Setter Property="HeaderTemplate" Value="{StaticResource GameNodeTemplate}"/>
</Style>
<Style x:Key="GenericTreeStyle" TargetType="{x:Type TreeView}">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF" Offset="0.0"/>
<GradientStop Color="#AAA" Offset="1.0"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="4"/>
<Setter Property="BorderBrush" Value="#FFA6AAAB"/>
</Style>
<cm:SortDescriptionCollection x:Key="AscendingNames">
<cm:SortDescription PropertyName="Source.(Logs:IGameLogsSource.Name)" Direction="Ascending"/>
</cm:SortDescriptionCollection>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</UserControl.Resources>
<Grid x:Name="RootGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" MinWidth="175"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<local:GameLogSourceTree x:Name="_gamesSourcesTree" TreeNodeStyle="{StaticResource GenericFolders}" TreeStyle="{StaticResource GenericTreeStyle}" NodeSortDescriptions="{StaticResource AscendingNames}"/>
<GridSplitter Grid.Column="0" HorizontalAlignment="Right" Width="2"/>
<local:LogControl x:Name="_gamesLogControl" Grid.Column="1"/>
</Grid>
下面是C#背后。
// C# code
namespace Test.UI
{
public partial class Noc : ILogListener
{
private readonly Dictionary<Guid, Tuple<LogMessageCollection, GameLogSourceNode>> _logInfo = new Dictionary<Guid, Tuple<LogMessageCollection, GameLogSourceNode>>();
public LogControl LogControl
{
get
{
return _gamesLogControl;
}
}
public Noc()
{
InitializeComponent();
_logInfo.Add(_gamesSourcesTree.GameRootNode.Source.Id, new Tuple<LogMessageCollection, GameLogSourceNode>(new LogMessageCollection(), _gamesSourcesTree.GameRootNode));
_logInfo.Add(_gamesSourcesTree.CoreRootNode.Source.Id, new Tuple<LogMessageCollection, GameLogSourceNode>(new LogMessageCollection(), _gamesSourcesTree.CoreRootNode));
_gamesSourcesTree.SelectedItem = _gamesSourcesTree.GameRootNode;
_gamesSourcesTree.NodeAdded += OnSourcesTreeNodeAdded;
_gamesSourcesTree.NodeRemoved += OnSourcesTreeNodeRemoved;
}
private void AddNodeIfNeeded(IGameLogsSource source)
{
IGameLogsSource i;
GameLogSourceNode item2;
if (_logInfo.ContainsKey(source.Id))
{
return;
}
var logSources = new Stack<IGameLogsSource>();
logSources.Push(source);
for (i = source.Parent; i != null && !_logInfo.ContainsKey(i.Id); i = i.Parent)
{
logSources.Push(i);
}
if (i != null)
{
item2 = _logInfo[i.Id].Item2;
}
else
{
i = logSources.Peek();
item2 = (i is Game ? _gamesSourcesTree.GameRootNode : _gamesSourcesTree.CoreRootNode);
}
foreach (var logSource in logSources)
{
var tuple = _logInfo.TryGetValue(logSource.Id);
if (tuple != null)
{
item2 = tuple.Item2;
}
else
{
var logSourceNode = new GameLogSourceNode(logSource, _gamesSourcesTree);
item2.ChildNodes.Add(logSourceNode);
item2 = logSourceNode;
}
}
}
public void Load(SettingsStorage storage)
{
storage.SetValue("LogControl", _gamesLogControl.Save());
}
private void OnSelectedItemChanged(object sender, RoutedTreeItemEventArgs<GameLogSourceNode> e)
{
_gamesLogControl.Messages = (e.NewItem != null ? _logInfo[e.NewItem.Source.Id].Item1 : new LogMessageCollection());
}
private void OnSourcesTreeNodeAdded(GameLogSourceNode node)
{
_logInfo.Add(node.Source.Id, new Tuple<LogMessageCollection, GameLogSourceNode>(new LogMessageCollection(), node));
}
private void OnSourcesTreeNodeRemoved(GameLogSourceNode node)
{
foreach (var childNode in node.ChildNodes)
{
OnSourcesTreeNodeRemoved(childNode);
}
_logInfo.Remove(node.Source.Id);
}
public void Save(SettingsStorage storage)
{
var value = storage.GetValue<SettingsStorage>("LogControl");
if (value != null)
{
((IPersistable)_gamesLogControl).Load(value);
}
}
public virtual void WriteMessage(LogMessage message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
WriteMessages(message.Source, new[] { message });
}
public virtual void WriteMessages(IEnumerable<LogMessage> messages)
{
if (messages == null)
{
throw new ArgumentNullException("messages");
}
(
from m in messages
group m by m.Source).ForEach<IGrouping<IGameLogsSource, LogMessage>>(g => WriteMessages(g.Key, g));
}
private void WriteMessages(IGameLogsSource source, IEnumerable<LogMessage> messages)
{
AddNodeIfNeeded(source);
for (var i = _logInfo[source.Id].Item2; i != null; i = i.ParentNode)
{
var item1 = _logInfo[i.Source.Id].Item1;
item1.AddRange(messages);
if (item1.Count > 2 * _gamesLogControl.MaxItemsCount && _gamesLogControl.MaxItemsCount > 0)
{
item1.RemoveRange(0, item1.Count - _gamesLogControl.MaxItemsCount);
}
}
}
}
}
答案 0 :(得分:0)
您将实际数据绑定到树的哪个位置?您需要设置树的ItemSource属性。既然你使用的是代码隐藏,我猜测它应该是这样的:
_gamesSourcesTree.ItemsSource = _logInfo;