首页 > 解决方案 > 将每个 TreeViewItem 分配给它自己的网格行

问题描述

我的最新努力 - 我已经设法用元素填充树视图,并用相关元素填充它旁边的列表框。

诀窍是,我试图想办法将每个列表框项和相应的树视图项分配给它自己的网格行,这可能会在后面的 C# 代码中生成,并根据控件的子项数使用相应的行定义,如果那有意义的话。

我尝试查看下面的帖子,看看是否可以通过这种方式选择每个树视图项目,但无济于事:

如何以编程方式选择 WPF TreeView 中的项目?

这是一些尝试实现此功能的示例代码-尽管如此,我一直在获取空值,并且在控件上的循环之前使用 UpdateLayout() 似乎没有帮助。:/

                for (int i = 0; i < loadedAR.Item2.Count; i++)
                {
                    DABsAndIssuesGrid.RowDefinitions.Add(new RowDefinition());
                    var selectedItemObjectDAB = DABView.Items.GetItemAt(i);
                    var DABParent = DABView.Parent;
                    TreeViewItem currentItemDAB = DABView.ItemContainerGenerator.ContainerFromItem(selectedItemObjectDAB)
                    as TreeViewItem;
                    if (currentItemDAB != null)
                        Grid.SetRow(currentItemDAB, i);
                    var selectedItemObjectErr = IssueBox.Items.GetItemAt(i);
                    TreeViewItem currentItemErr = DABView.ItemContainerGenerator.ContainerFromItem(selectedItemObjectErr)
                    as TreeViewItem;
                    if (currentItemErr != null)
                        Grid.SetRow(currentItemErr, i);
                }

有没有比我尝试做的更好的方法来做到这一点?我已经尝试使用转换器动态分配行,因为它们会生成,但这似乎仍然将我所有的孩子放在同一个网格行中......

这是我的 XAML:

<Window x:Class="Client_Invoice_Auditor.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Client_Invoice_Auditor"
        xmlns:self="clr-namespace:Client_Invoice_Auditor.CoreClient"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="1000">
    <Window.Resources>
        <self:SelfPayConverter x:Key="FINConverter"/>
        <self:ErrorExpandConverter x:Key="ErrorExpandConverter"/>
        <self:AssignRowConverter x:Key="AssignRowConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>

        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20*"/>
            <RowDefinition Height="80*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Grid.Column="0">
            <StackPanel Orientation="Vertical">
                <DockPanel VerticalAlignment="Top" Height="20" Panel.ZIndex="1">
                    <Menu Name="fileMenu" Width="Auto" DockPanel.Dock="Top">
                        <MenuItem Header="File">
                            <MenuItem Header="Open Account File" Click="menuOpenFile_Click"/>

                            <MenuItem Header="Exit" Click="menuExit_Click"/>
                        </MenuItem>
                        <MenuItem Header="Options">
                            <!--<MenuItem Header="Update" Click="update_Click"/>-->
                            <MenuItem Header="About" Click="about_Click"/>
                        </MenuItem>
                    </Menu>
                </DockPanel>
                <WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" Height="Auto">
                    <StackPanel Width="Auto" Orientation="Horizontal" HorizontalAlignment="Center">
                        <Border BorderBrush="MediumAquamarine" BorderThickness="2">
                            <Label Name="AccountNumber"/>
                        </Border>
                        <Border BorderBrush="MediumAquamarine" BorderThickness="2">
                            <Label Name="AcctDesc"/>
                        </Border>
                        <Border BorderBrush="MediumAquamarine" BorderThickness="2">
                            <Label Name="Organization"/>
                        </Border>
                    </StackPanel>
                </WrapPanel>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                    <Label Margin="20,10,0,0" Content="Activity Date Time" />
                    <Label Margin="60,10,0,0" Content="Beginning Balance" />
                    <Label Margin="10,10,0,0" Content="Charge Amount" />
                    <Label Margin="30,10,0,0" Content="Adjustments" />
                    <Label Margin="40,10,0,0" Content="Payments" />
                    <Label Margin="60,10,0,0" Content="End Balance" />
                    <Label Margin="50,10,0,0" Content="Issues" />
                </StackPanel>
            </StackPanel>

        </Grid>
        <Grid Grid.Row="1" Grid.Column="0">
            <Grid Name="DABsAndIssuesGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80*"/>
                    <ColumnDefinition Width="20*"/>
                </Grid.ColumnDefinitions>
                <TreeView Name="DABView" Grid.Column="0">
                    <!--<Style TargetType="{x:Type TreeViewItem}">
                        <Setter Property="IsExpanded" 
                                                Value="{Binding FinClass, Converter={StaticResource ErrorExpandConverter}}" />
                    </Style>-->
                    <TreeView.ItemContainerStyle>
                        <Style TargetType="{x:Type TreeViewItem}">
                            <Setter Property="IsExpanded" 
                                                Value="{Binding Dummies, Converter={StaticResource ErrorExpandConverter}}" />
                        </Style>
                    </TreeView.ItemContainerStyle>
                    <TreeView.ItemTemplate>

                        <HierarchicalDataTemplate DataType="{x:Type self:dailyAccountBalance}" ItemsSource="{Binding Dummies}">

                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" IsEnabled="False">
                                    <TextBlock Width="150" Text="{Binding DabActivityDate}" />
                                    <TextBlock Width="100" Margin="20,0,0,0" Text="{Binding BegBalance}"/>
                                    <TextBlock Width="100" Margin="20,0,0,0" Text="{Binding ChrgAmount}" />
                                    <TextBlock Width="100" Margin="20,0,0,0" Text="{Binding AdjAmount}" />
                                    <TextBlock Width="100" Margin="20,0,0,0" Text="{Binding PmtAmount}" />
                                    <TextBlock Width="100" Margin="20,0,0,0" Text="{Binding EndBalance}" />
                                </StackPanel>

                            <HierarchicalDataTemplate.ItemTemplate>

                                <DataTemplate DataType="{x:Type self:DummyItem}">

                                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                                        <!--<TextBlock Text="{Binding Text}" />-->
                                        <DataGrid ItemsSource="{Binding ChargeActivities}" AutoGenerateColumns="False">

                                            <DataGrid.Style>
                                                <Style TargetType="{x:Type DataGrid}">
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding Path=Items.Count,
                                                                RelativeSource={RelativeSource Self}}"  Value="0">
                                                            <Setter Property="Visibility" Value="Collapsed" />
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </DataGrid.Style>

                                            <DataGrid.Columns>
                                                <DataGridTextColumn x:Name="ChrgID"  Header=" Charge" Binding="{Binding ChargeID}" />
                                                <DataGridTextColumn x:Name="ChrgType"  Header="Charge Type" Binding="{Binding ChargeType}">
                                                    <DataGridTextColumn.ElementStyle>
                                                        <Style TargetType="{x:Type TextBlock}">
                                                            <Style.Triggers>
                                                                <Trigger Property="Text" Value="CR">
                                                                    <Setter Property="Foreground" Value="Red"/>
                                                                </Trigger>
                                                            </Style.Triggers>
                                                        </Style>
                                                    </DataGridTextColumn.ElementStyle>
                                                </DataGridTextColumn>
                                                <DataGridTextColumn x:Name="ChrgAmt"  Header="Amount" Binding="{Binding ChargeAmount}">
                                                    <DataGridTextColumn.ElementStyle>

                                                        <Style TargetType="{x:Type TextBlock}">
                                                            <Style.Triggers>
                                                                <DataTrigger Binding="{Binding ChargeType}" Value="CR">
                                                                    <Setter Property="Foreground" Value="Red"/>
                                                                </DataTrigger>
                                                            </Style.Triggers>
                                                        </Style>
                                                    </DataGridTextColumn.ElementStyle>
                                                </DataGridTextColumn>
                                                <DataGridTextColumn x:Name="FIN"  Header="FIN" Binding="{Binding EncntrAlias}" />
                                                <DataGridTextColumn x:Name="FINClass"  Header="FIN Class" Binding="{Binding FinClass}">
                                                    <DataGridTextColumn.ElementStyle>
                                                        <Style TargetType="{x:Type TextBlock}">
                                                            <Setter Property="Foreground" Value="{Binding FinClass, Converter={StaticResource FINConverter}}"/>
                                                        </Style>
                                                    </DataGridTextColumn.ElementStyle>
                                                </DataGridTextColumn>
                                            </DataGrid.Columns>
                                        </DataGrid>
                                    </StackPanel>
                                </DataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>

                    </HierarchicalDataTemplate>

                        <!--<TreeViewItem x:Key="Test">
                            <TextBlock Text="Me gusta"></TextBlock>
                        </TreeViewItem>-->
                    </TreeView.ItemTemplate>
                </TreeView>
                <Border Grid.Column="1" BorderBrush="Black" BorderThickness="2">
                    <ListBox Name="IssueBox" ItemsSource="{Binding}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="Hi"/>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </Border>
            </Grid>
        </Grid>
    </Grid>
</Window>

而且,这是背后的代码:

using Client_Invoice_Auditor.CoreClientAR;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Client_Invoice_Auditor
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public string accountFile;
        public MainWindow()
        {
            InitializeComponent();
            OpenaccountFile();
        }

        private void OpenaccountFile()
        {
            accountFile = "";
            //errorFilters.Clear();
            // Displays an OpenFileDialog so the user can select a file.  
            Microsoft.Win32.OpenFileDialog openFileDialog1 = new Microsoft.Win32.OpenFileDialog();
            openFileDialog1.Filter = "Account Files|*.acct";
            openFileDialog1.Title = "Select an account File";

            if (openFileDialog1.ShowDialog() == true)
            {
                // Assign the cursor in the Stream to the Form's Cursor property.
                accountFile = openFileDialog1.FileName;
                //claimFile = openFileDialog1.OpenFile().ToString();
                //openFileDialog1.Dispose();
            }
            if (accountFile == "")
            {
                /*System.Windows.MessageBox.Show("File must be selected in order to continue - exiting now."
                    , "No File Selected", MessageBoxButton.OK);
                this.Close();*/
                if (!AcctDesc.HasContent)
                {
                    AcctDesc.Content = "No Account File Loaded";
                    //Version version = Assembly.GetExecutingAssembly().GetName().Version;
                    //manualBreakItem.IsEnabled = false;
                    //manualValidateItem.IsEnabled = false;
                }
            }
            else
            {
                //openFileDialog1 = null;
                Console.WriteLine("Account file path is: " + accountFile);
                //claimFile = "C:\\Users\\KO054202\\Documents\\pft_1450_out\\pft_1450_out\\CAR837I125114220170601.out";
                DataTable dataAR = new DataTable();

                try
                {
                    Tuple<accountARHeader, List<dailyAccountBalance>, DataTable> loadedAR = dabARLoader.LoadARData(accountFile);
                    //dataAR = loadedAR.Item2;
                    AccountNumber.Content = "Account Number: " + loadedAR.Item1.AccountNumber;
                    AcctDesc.Content = "Description: " + loadedAR.Item1.AccountDescription;
                    Organization.Content = "Client Organization: " + loadedAR.Item1.OrganizationName;
                    //TreeViewItem dummy = new TreeViewItem();
                    //dummy.DataContext = "Hi";
                    //DummyItem testThis = new DummyItem("Test2");
                    //testThis.Text = "Hi";
                    //loadedAR.Item2.First().Dummies.Add(testThis);
                    DABView.ItemsSource = loadedAR.Item2;
                    IssueBox.ItemsSource = dabARLoader.loadIssues(loadedAR.Item2);
                    DABView.UpdateLayout();
                    for (int i = 0; i < loadedAR.Item2.Count; i++)
                    {
                        DABsAndIssuesGrid.RowDefinitions.Add(new RowDefinition());
                        var selectedItemObjectDAB = DABView.Items.GetItemAt(i);
                        var DABParent = DABView.Parent;
                        TreeViewItem currentItemDAB = DABView.ItemContainerGenerator.ContainerFromItem(selectedItemObjectDAB)
                        as TreeViewItem;
                        if (currentItemDAB != null)
                            Grid.SetRow(currentItemDAB, i);
                        var selectedItemObjectErr = IssueBox.Items.GetItemAt(i);
                        TreeViewItem currentItemErr = DABView.ItemContainerGenerator.ContainerFromItem(selectedItemObjectErr)
                        as TreeViewItem;
                        if (currentItemErr != null)
                            Grid.SetRow(currentItemErr, i);
                    }


                    //DABView.DisplayMemberPath = "A";
                }
                catch (Exception e)
                {
                    System.Windows.MessageBox.Show("I don't wanna open this file! Try another. Error: " + e.Message);
                    OpenaccountFile();
                }

            }
        }

        private void menuOpenFile_Click(object sender, RoutedEventArgs e)
        {
            OpenaccountFile();
        }

        private void menuExit_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        private void about_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.MessageBox.Show("I heard you like clicking buttons.");
        }
    }
}

标签: c#wpfgridviewlistboxtreeview

解决方案


我在 Grid 中有一个 TreeView 以及一个 ListBox 控件。这个想法是 TreeView 将通过每日帐户余额填充父项,然后对于其中的每一项,相邻的问题列表将显示在相邻的 ListBox 中

我将制作专门的数据传输对象 (DTO),其中每个实例项生成要显示的属性的值,并在需要时为该实例创建子 DTO。然后这些 DTO 可以在所有控件之间绑定。这意味着您定义了此类

<Top Level Class used by the grid<DTO>>
   <Properties et all>
   <List of Items in for treeview>
      <Treeview class <DTO>>
          <Properties et all>
          <List of Items in for listbox>
              <Listbox class <DTO>>
              <Properties et all>
  1. 然后将网格绑定到上面的顶级 DTO 列表。
  2. 将树视图绑定到当前行的树视图列表项。
  3. 将列表框绑定到当前树视图的选定项的列表框项列表。

一旦创建了 DTO,它就变成了绑定练习。


推荐阅读