【问题标题】:Multiple DataContext one TreeView one DataGrid both can't be active at the same time多个DataContext 一TreeView 一DataGrid 不能同时处于活动状态
【发布时间】:2020-08-03 07:29:38
【问题描述】:

我在 youtube 视频之后创建了一个树视图,然后创建了一个数据网格,显示来自所选 tar.gz 文件的一些文件。他们都使用 DataContext 在程序中展示自己。问题是显示 DataGrid 时 TreeView 消失了。我想问题是两者都不能像我使用的那样使用 DataContext 但我不知道它的解决方案。

XAML 代码

<Window x:Class="RFAnalyzerMain.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:RFAnalyzerMain"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="600" Width="900"
        MinHeight="400" MinWidth="750"
        Closing="Window_Closing" Loaded="Window_Loaded">
    <Border Padding="2">
        <Grid>
            <!-- #region Grid Definitions -->

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" />
                <ColumnDefinition Width="10*" />
                <ColumnDefinition Width="15" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="20" />
                <RowDefinition Height="20" />
                <RowDefinition Height="25*" />
                <RowDefinition Height="20" />
            </Grid.RowDefinitions>

            <!--#endregion-->

            <DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
                <Menu DockPanel.Dock="Top">
                    <MenuItem Header="_File">
                        <MenuItem Header="Choose File to Read" x:Name="ChosenFile" Click="ChosenFile_Click" />
                    </MenuItem>
                </Menu>
            </DockPanel>

            <Border Grid.Row="2" Padding="5 0" BorderThickness="0" BorderBrush="Gray">
                <Grid>

                    <!-- Grid Definitions -->
                    <Grid.RowDefinitions>
                        <RowDefinition Height="25" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="20" />
                    </Grid.RowDefinitions>

                    <TextBlock Text="Folder" FontWeight="Bold" FontSize="18" Grid.Row="0"
                       VerticalAlignment="Center" HorizontalAlignment="Left" />

                    <!-- A TreeView of Fodlers -->
                    <Grid Grid.Row="1" Margin="0 0 0 5">
                        <TreeView x:Name="FolderView" ItemsSource="{Binding Items}" FontSize="10">
                            
                            <TreeView.ItemContainerStyle>
                                <Style TargetType="{x:Type TreeViewItem}">
                                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                                </Style>
                            </TreeView.ItemContainerStyle>

                            <TreeView.ItemTemplate>
                                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                                    <StackPanel Orientation="Horizontal">
                                        <Image Width="15" Margin="3"
                                                   Source="{Binding Type,
                                                       Converter={x:Static local:HeaderToImageConverter.Instance}}" />
                                        <TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
                                    </StackPanel>
                                </HierarchicalDataTemplate>
                            </TreeView.ItemTemplate>
                            
                        </TreeView>
                    </Grid>


                    <Button Content="Read" Grid.Row="2" Margin="0 0 0 0" Width="60" />
                </Grid>
            </Border>

            <DataGrid Grid.Row="2" Grid.Column="1" ItemsSource="{Binding FileProperties}" />

            <Button Grid.Column="2" Grid.Row="2">
                <Image Source="Images/Button Left Arrow.png" Width="10" />
            </Button>

        </Grid>
    </Border>
</Window>

代码后面

using System.IO;
using System.Windows;

namespace RFAnalyzerMain
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Constructor

        /// <summary>
        /// Default Constructor
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
            // Treeview
            DataContext = new DirectoryStructureViewModel();
        }

        #endregion

        #region User Events

        /// <summary>
        /// Choose a file from the explorer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ChosenFile_Click(object sender, RoutedEventArgs e)
        {
            ExplorerHandler.OpenExplorer();
            // Writes out all the files inside the file opened in the explorer
            DataContext = new FilePropertiesViewModel();
        }

        #endregion

        #region Starting Program

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (FilePaths.GZipDirectory.Exists == true)
                Remove.FilesAndFolders();
        }

        #endregion

        #region Closing Program

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Remove.FilesAndFolders();
        }

        #endregion


    }
}

如果您需要查看更多代码,请询问,我会编辑帖子并添加要求的代码。

【问题讨论】:

  • 创建另一个视图模型(将其设置为窗口的DataContext 一次!)并将这些视图模型添加为仅限 getter 的属性。然后你可以将ItemsSources 绑定到FirtVMProperty.ItemsAnotherVMProperty.FileProperties
  • @Sinatr 好的,谢谢!这会像我希望 DataGrid 为空并且仅在选择文件时显示一样工作吗?
  • 您可以简单地控制DataGrid 的可见性(并显示文本“首先选择文件”)或者该属性可以在getter 中有逻辑返回empty 视图模型如果文件没有被选中。
  • 或者在树视图项目视图模型的属性中创建集合并绑定到所选树视图节点上的该属性。你需要一种行为来做到这一点,但很容易被谷歌搜索到。当没有选择任何内容时,数据网格没有任何内容,所以它是空的。
  • @Sinatr 有没有一种方法可以展示如何将两个视图模型添加到我创建的这个新类中,它将成为 DataContext? :)

标签: c# wpf


【解决方案1】:

既然你在代码隐藏中实现了你的逻辑,为什么不在事件处理程序中简单地设置DataGridDataContext 呢?:

private void ChosenFile_Click(object sender, RoutedEventArgs e)
{
    ExplorerHandler.OpenExplorer();
    // Writes out all the files inside the file opened in the explorer
    dataGrid.DataContext = new FilePropertiesViewModel();
}

XAML:

<DataGrid x:Name="dataGrid" Grid.Row="2" Grid.Column="1" ItemsSource="{Binding FileProperties}" />

那么当你点击按钮时TreeView不会消失。

另一种选择是使用@Sinatr 建议的共享视图模型,但这需要对您当前拥有的内容进行一些重构。

【讨论】:

  • 谢谢!这解决了我的问题! :)
【解决方案2】:

通常你必须设置一次DataContext

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainWindowViewModel();
}

视图模型可以有多个属性:

public class MainWindowViewModel: INotifyPropertyChanaged
{
    public DirectoryStructureViewModel Files { get; } = new DirectoryStructureViewModel();

    FilePropertiesViewModel _selectedFile;
    public FilePropertiesViewModel SelectedFile
    {
        get => _selectedFile;
        set
        {
            _selectedFile = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(IsSelectedFileVisible));
        }
    }
    public bool IsSelectedFileVisible => SelectedFile != null;
}

您可以在视图中绑定的对象:

<TreeView ItemsSource="{Binding Files.Items}"
          SelectedItemChanged="TreeView_OnSelectedItemChanged" ... />
<DataGrid ItemsSource="{Binding SelectedFile.FileProperties}"
          Visibility="{Binding IsSelectedFileVisible, Converter={StaticResource BoolToVis}}" ... />

void TreeView_OnSelectedItemChanged(...)
{
    var vm = (MainWindowViewModel)DataContext;
    vm.SelectedFile = ...
}

参考:123

【讨论】:

    猜你喜欢
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2023-04-04
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多