1

这是我的简化 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="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>

绑定按预期工作,数据集中父表的 feed_title 绑定到树视图中的顶部节点。然后,该特定提要(数据集的子表)中的所有项目都作为子节点绑定到树视图中的该顶部节点。

我想要实现的目标:我想向顶部节点添加更多信息,而不仅仅是 feed_title。我想从子表中读取哪些项目是否同步,并更新顶部节点以包含如下文本:“(4/10)标题”。这样它就会通知用户 10 个项目中只有 4 个是同步的。我不需要解决方案,但想知道如何解决这个问题......

4

3 回答 3

2

为了说明@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();
        }
    }
}

项目视图模型.cs

using System.ComponentModel;

namespace WpfApplication11
{
    public class ItemViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate {};

        private string itemName;
        private bool isSynchronized;

        public string ItemName
        {
            get { return itemName; }
            set
            {
                itemName = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ItemName"));
            }
        }

        public bool IsSynchronized
        {
            get { return isSynchronized; }
            set
            {
                isSynchronized = value;
                PropertyChanged(this,
                                new PropertyChangedEventArgs("IsSynchronized"));
            }
        }
    }
}

DataSetCreator.cs - 这只是两个模拟 - DataSetDataSetCreator用于您在代码中提到的类,因此请随意使用您自己的):

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

最后,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>
于 2013-06-19T13:47:19.697 回答
1

我建议您构建一个自定义模型或视图模型来处理孩子和父母之间的这些复杂关系。例如:

  1. 创建两个名为 Parent 和 Child 的类。
  2. 每个类都具有保存其相应数据集的属性。
  3. 父母有他们孩子的集合。
  4. Child 实现INotifyPropertyChanged,因此父母可以订阅PropertyChanged事件并知道何时读取了孩子(并跟踪该事件)。

最后,您绑定到类属性而不是数据集。请记住INotifyPropertyChanged在要绑定或使用的属性中实现DependencyProperties

这里有一些关于实现的技巧INotifyPropertyChanged

于 2013-06-15T23:17:06.747 回答
0

我认为您的模型或视图模型层具有诸如“IsSynchronized”之类的属性来指示其状态。如果是这种情况,我建议您在绑定中使用 Converter(可能继承自 IValueConverter)。在转换器实现中,您可以获取所有孩子的同步状态并将计算出的数字返回给 UI 元素。

当然,您必须实现 INotifyPropertyChanged 接口。

于 2013-06-17T09:04:47.927 回答