Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF将textblock绑定到父表中的列,此外还解析childtable并为textblock设置适当的值_C#_Wpf_Xaml_Dataset - Fatal编程技术网

C# WPF将textblock绑定到父表中的列,此外还解析childtable并为textblock设置适当的值

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

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

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


我试图实现的目标是:我想向顶部节点添加更多信息,而不仅仅是提要标题。我想从子表中读取哪些项目已同步或未同步,并更新顶部节点以包含如下文本:“(4/10)Title”。所以它会通知用户10个项目中只有4个是同步的。我不需要解决方案,但想知道如何进行…

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

  • 创建两个名为Parent和Child的类
  • 每个类都有保留其相应数据集的属性
  • 父对象有其子对象的集合
  • Child实现了
    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-对于您在代码中提到的类,这只是两个模拟-DataSetDataSetCreator,所以请随意使用您自己的):

    使用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>