C# WPF将textblock绑定到父表中的列,此外还解析childtable并为textblock设置适当的值
这是我的简化XAML:C# WPF将textblock绑定到父表中的列,此外还解析childtable并为textblock设置适当的值,c#,wpf,xaml,dataset,C#,Wpf,Xaml,Dataset,这是我的简化XAML: <Window x:Class="MyForm.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MyForm" Title="MyFo
<Window x:Class="MyForm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyForm"
Title="MyForm" Closing="Window_Closing" Icon="Images\main.ico" Height="633" Width="1602" Loaded="Window_Loaded" xmlns:my="clr-namespace:MyForm">
<Window.Resources>
<ObjectDataProvider x:Key="dataSetProvider" MethodName="CreateDataSet" ObjectType="{x:Type local:DataSetCreator}" />
<DataTemplate x:Key="ItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding item_title}">
</TextBlock>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="FeedTemplate" ItemsSource="{Binding FK_FM_FEEDS_FEED_0_0}" ItemTemplate="{StaticResource ItemTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding feed_title}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView LayoutUpdated="treeViewMain_LayoutUpdated" TreeViewItem.Expanded="TextBlock_Expanded" Name="treeViewMain" DataContext="{StaticResource dataSetProvider}" ItemsSource="{Binding FM_FEEDS_FEEDS}" ItemTemplate="{StaticResource FeedTemplate}">
</TreeView>
</Grid>
</Window>
绑定按预期工作,数据集中父表的提要标题绑定到树视图中的顶部节点。然后,该特定提要(dataset的childtable)中的所有项都作为子节点绑定到树视图中的顶部节点
我试图实现的目标是:我想向顶部节点添加更多信息,而不仅仅是提要标题。我想从子表中读取哪些项目已同步或未同步,并更新顶部节点以包含如下文本:“(4/10)Title”。所以它会通知用户10个项目中只有4个是同步的。我不需要解决方案,但想知道如何进行…我建议您构建一个自定义模型或viewModel来处理孩子和家长之间的这些复杂关系。例如:
INotifyPropertyChanged
,因此家长可以订阅PropertyChanged
事件,并知道何时读取了一个子项(并跟踪该项)INotifyPropertyChanged
,或使用dependencProperties
有一些关于实现INotifyPropertyChanged的技巧我认为您的模型或viewmodel层有一些类似“IsSynchronized”的属性来指示其状态。如果是这种情况,我建议您在绑定中使用转换器(可能继承自IValueConverter)。在转换器实现中,您可以获取所有子级的同步状态,并将计算出的数字返回到UI元素
当然,您必须实现INotifyPropertyChanged接口。为了说明@mikehc建议的方法将如何工作,请查看以下工作代码示例: FeedViewModel.cs-请注意,它使用计时器定期刷新标题(本代码中为1秒,或您喜欢/需要的任何内容),以及来自其子级同步状态的信息。这是一个更简单的解决方案,而不是订阅其每个子项的事件,以便在同步时收到通知,处理添加新的和删除旧的子项等问题:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Threading;
namespace WpfApplication11
{
public class FeedViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate {};
DispatcherTimer timer =
new DispatcherTimer(DispatcherPriority.Background);
private string feedName;
public string FeedName
{
get { return feedName; }
set
{
feedName = value;
PropertyChanged(this,
new PropertyChangedEventArgs("FeedName"));
PropertyChanged(this,
new PropertyChangedEventArgs("FeedTitle"));
}
}
public ObservableCollection<ItemViewModel> FeedItems { get; set; }
public string FeedTitle
{
get
{
return string.Format("({0}/{1}) {2}",
FeedItems.Count(item => item.IsSynchronized),
FeedItems.Count,
FeedName);
}
}
public FeedViewModel()
{
FeedItems = new ObservableCollection<ItemViewModel>();
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += (sender, args) =>
PropertyChanged(this,
new PropertyChangedEventArgs("FeedTitle"));
timer.Start();
}
}
}
DataSetCreator.cs-对于您在代码中提到的类,这只是两个模拟-DataSet和DataSetCreator,所以请随意使用您自己的):
使用System.Collections.ObjectModel;
命名空间WpfApplication11
{
公共类数据集
{
公共ObservableCollection提要{get;private set;}
公共数据集()
{
Feeds=新的可观察集合
{
新的FeedViewModel
{
FeedName=“Feed#1”,
FeedItems=新的可观察集合
{
新的ItemViewModel
{
ItemName=“Item#1.1”,
IsSynchronized=true
},
新的ItemViewModel
{
ItemName=“Item#1.2”,
IsSynchronized=true
},
新的ItemViewModel
{
ItemName=“Item#1.3”,
IsSynchronized=false
},
}
},
新的FeedViewModel
{
FeedName=“Feed#2”,
FeedItems=新的可观察集合
{
新的ItemViewModel
{
ItemName=“Item#2.1”,
IsSynchronized=true
},
新的ItemViewModel
{
ItemName=“Item#2.2”,
IsSynchronized=true
},
}
},
新的FeedViewModel
{
FeedName=“Feed#3”,
FeedItems=新的可观察集合
{
新的ItemViewModel
{
ItemName=“Item#3.1”,
IsSynchronized=false
},
新的ItemViewModel
{
ItemName=“Item#3.2”,
IsSynchronized=false
},
}
}
};
}
}
公共类DataSetCreator
{
公共数据集CreateDataSet()
{
返回新数据集();
}
}
}
最后,MainWindow.xaml-更新为使用上面的模拟类DataSetCreator.cs:
<Window x:Class="WpfApplication11.MainWindow"
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"
xmlns:local="clr-namespace:WpfApplication11"
mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ItemViewModel x:Key="DesignItemViewModel" />
<local:FeedViewModel x:Key="DesignFeedViewModel" />
<ObjectDataProvider x:Key="dataSetProvider"
ObjectType="{x:Type local:DataSetCreator}"
MethodName="CreateDataSet" />
<DataTemplate x:Key="ItemTemplate">
<StackPanel Orientation="Horizontal"
d:DataContext="{StaticResource DesignItemViewModel}">
<TextBlock Text="{Binding Path=ItemName}" />
<CheckBox IsChecked="{Binding Path=IsSynchronized}"
Margin="25,0,0,0"
Content=" is synchronized?"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="FeedTemplate"
ItemsSource="{Binding Path=FeedItems}"
ItemTemplate="{StaticResource ItemTemplate}">
<StackPanel Orientation="Horizontal"
d:DataContext="{StaticResource DesignFeedViewModel}">
<TextBlock Text="{Binding Path=FeedTitle}" />
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView DataContext="{StaticResource dataSetProvider}"
d:DataContext="{StaticResource dataSetProvider}"
ItemsSource="{Binding Path=Feeds}"
ItemTemplate="{StaticResource FeedTemplate}" />
</Grid>
</Window>
要归档这种灵活性,您需要通过视图模型类和其他与UI相关的逻辑来实现额外的抽象级别。它们将位于原始数据集对象和UI元素(用XAML声明)之间
using System.Collections.ObjectModel;
namespace WpfApplication11
{
public class DataSet
{
public ObservableCollection<FeedViewModel> Feeds { get; private set; }
public DataSet()
{
Feeds = new ObservableCollection<FeedViewModel>
{
new FeedViewModel
{
FeedName = "Feed #1",
FeedItems = new ObservableCollection<ItemViewModel>
{
new ItemViewModel
{
ItemName = "Item #1.1",
IsSynchronized = true
},
new ItemViewModel
{
ItemName = "Item #1.2",
IsSynchronized = true
},
new ItemViewModel
{
ItemName = "Item #1.3",
IsSynchronized = false
},
}
},
new FeedViewModel
{
FeedName = "Feed #2",
FeedItems = new ObservableCollection<ItemViewModel>
{
new ItemViewModel
{
ItemName = "Item #2.1",
IsSynchronized = true
},
new ItemViewModel
{
ItemName = "Item #2.2",
IsSynchronized = true
},
}
},
new FeedViewModel
{
FeedName = "Feed #3",
FeedItems = new ObservableCollection<ItemViewModel>
{
new ItemViewModel
{
ItemName = "Item #3.1",
IsSynchronized = false
},
new ItemViewModel
{
ItemName = "Item #3.2",
IsSynchronized = false
},
}
}
};
}
}
public class DataSetCreator
{
public DataSet CreateDataSet()
{
return new DataSet();
}
}
}
<Window x:Class="WpfApplication11.MainWindow"
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"
xmlns:local="clr-namespace:WpfApplication11"
mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ItemViewModel x:Key="DesignItemViewModel" />
<local:FeedViewModel x:Key="DesignFeedViewModel" />
<ObjectDataProvider x:Key="dataSetProvider"
ObjectType="{x:Type local:DataSetCreator}"
MethodName="CreateDataSet" />
<DataTemplate x:Key="ItemTemplate">
<StackPanel Orientation="Horizontal"
d:DataContext="{StaticResource DesignItemViewModel}">
<TextBlock Text="{Binding Path=ItemName}" />
<CheckBox IsChecked="{Binding Path=IsSynchronized}"
Margin="25,0,0,0"
Content=" is synchronized?"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="FeedTemplate"
ItemsSource="{Binding Path=FeedItems}"
ItemTemplate="{StaticResource ItemTemplate}">
<StackPanel Orientation="Horizontal"
d:DataContext="{StaticResource DesignFeedViewModel}">
<TextBlock Text="{Binding Path=FeedTitle}" />
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView DataContext="{StaticResource dataSetProvider}"
d:DataContext="{StaticResource dataSetProvider}"
ItemsSource="{Binding Path=Feeds}"
ItemTemplate="{StaticResource FeedTemplate}" />
</Grid>
</Window>