简体   繁体   English

如何在 xaml 中通过 DataTrigger 切换控制?

[英]How to switch Control by DataTrigger in the xaml?

There is a window consist of the two control.有一个窗口由两个控件组成。 one is TreeView, the other is ListBox.一个是TreeView,另一个是ListBox。

The code is as shown below.代码如下所示。

<Grid Grid.Row="1">
    <TreeView x:Name="treeView" BorderThickness="0" Visibility="Visible"
                ItemsSource="{Binding TotalCPUs}">

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectedItemChanged">
                <mvvm:EventToCommand Command="{Binding CPUSelectedCommand}"
                                 PassEventArgsToCommand="True"
                                 EventArgsConverter="{localConverters:SelectedItemConverter}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TreeView>

    <ListBox x:Name="listBox" BorderThickness="0" Visibility="Collapsed"/>
</Grid>

Now I would like to change the value of the Visibility property of the Control whenever changes property of the ViewModel.现在,每当更改 ViewModel 的属性时,我想更改 Control 的 Visibility 属性的值。 (FilterMode True = ListBox Visible, FilterMode False = TreeView = Visible) (FilterMode True = ListBox Visible, FilterMode False = TreeView = Visible)

To this, I modified my XAML code as below.为此,我修改了我的 XAML 代码,如下所示。

<Grid Grid.Row="1">
    <TreeView x:Name="treeView" BorderThickness="0" Visibility="Visible"
                ItemsSource="{Binding TotalCPUs}">
        <TreeView.Style>
            <Style TargetType="{x:Type TreeView}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding FilterMode}" Value="true">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>                                
            </Style>
        </TreeView.Style>

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectedItemChanged">
                <mvvm:EventToCommand Command="{Binding CPUSelectedCommand}"
                                 PassEventArgsToCommand="True"
                                 EventArgsConverter="{localConverters:SelectedItemConverter}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TreeView>

    <ListBox x:Name="listBox" BorderThickness="0" Visibility="Collapsed">
        <ListBox.Style>
            <Style TargetType="{x:Type ListBox}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding FilterMode}" Value="true">
                        <Setter Property="Visibility" Value="Visible"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
    </ListBox>
</Grid>

Below is the ViewModel code.下面是 ViewModel 代码。

public class NewProjectViewModel : DialogViewModel
{
    private Generator projectGenerator = new Generator();

    public ObservableCollection<ClassHierarchyData> TotalCPUs { get; private set; } = new ObservableCollection<ClassHierarchyData>();
    public ObservableCollection<DetailType> FilterCPUs { get; private set; } = new ObservableCollection<DetailType>();

    private bool filterMode;
    public bool FilterMode
    {
        get => filterMode;
        set
        {
            if (this.filterMode == value) return;
            this.filterMode = value;
            this.RaisePropertyChanged("FilterMode");
        }
    }

    private string cpuSearch;
    public string CPUSearch
    {
        get => this.cpuSearch;
        set
        {
            if (this.cpuSearch == value) return;
            this.cpuSearch = value;
            this.FilterCPUs.Add(new DetailType(typeof(Target), "abc"));
        }
    }

    private Type selectedTerminalItem;
    public Type SelectedTerminalItem
    {
        get => this.selectedTerminalItem;
        private set
        {
            if (this.selectedTerminalItem == value) return;
            this.selectedTerminalItem = value;

            this.RaisePropertyChanged("SelectedTerminalItem");
        }
    }

    private Type selectedItem;
    public Type SelectedItem
    {
        get => selectedItem;
        set
        {
            if (this.selectedItem == value) return;
            this.selectedItem = value;
            this.RaisePropertyChanged("SelectedItem");

            CreateCommand.RaiseCanExecuteChanged();
        }
    }

    private string solutionName = string.Empty;
    public string SolutionName
    {
        get => this.solutionName;
        set
        {
            if (this.solutionName == value) return;

            this.solutionName = value;
            this.RaisePropertyChanged("SolutionName");
            this.RaisePropertyChanged("SolutionFullPath");

            CreateCommand.RaiseCanExecuteChanged();
        }
    }

    private string solutionPath = string.Empty;
    public string SolutionPath
    {
        get => this.solutionPath;
        set
        {
            if (this.solutionPath == value) return;

            this.solutionPath = value;
            if(this.SolutionPath.Length > 0)
            {
                if (this.solutionPath.Last() != '\\')
                    this.solutionPath += "\\";
            }
            this.RaisePropertyChanged("SolutionPath");
            this.RaisePropertyChanged("SolutionFullPath");

            CreateCommand.RaiseCanExecuteChanged();
        }
    }

    public bool CreateSolutionFolder { get; set; }
    public string SolutionFullPath { get => this.SolutionPath + this.solutionName; }

    private RelayCommand searchCommand;
    public RelayCommand SearchCommand
    {
        get
        {
            if (this.searchCommand == null) this.searchCommand = new RelayCommand(this.OnSearch);

            return this.searchCommand;
        }
    }
    private void OnSearch()
    {
        CommonOpenFileDialog selectFolderDialog = new CommonOpenFileDialog();

        selectFolderDialog.InitialDirectory = "C:\\Users";
        selectFolderDialog.IsFolderPicker = true;
        if (selectFolderDialog.ShowDialog() == CommonFileDialogResult.Ok)
        {
            this.SolutionPath = selectFolderDialog.FileName + "\\";
        }
    }

    private RelayCommand<Action> _createCommand;
    public RelayCommand<Action> CreateCommand
    {
        get
        {
            if (this._createCommand == null)
                this._createCommand = new RelayCommand<Action>(this.OnCreate, this.CanExecuteCreate);

            return this._createCommand;
        }
    }
    private void OnCreate(Action action)
    {
        projectGenerator.GenerateSolution(this.SolutionPath, this.SolutionName, this.CreateSolutionFolder);
        action?.Invoke();
    }

    private bool CanExecuteCreate(Action action)
    {
        if (this.SelectedTerminalItem == null) return false;
        if (string.IsNullOrEmpty(this.solutionPath)) return false;
        if (string.IsNullOrEmpty(this.solutionName)) return false;

        return true;
    }

    private RelayCommand<ClassHierarchyData> cpuSelectedCommand;
    public RelayCommand<ClassHierarchyData> CPUSelectedCommand
    {
        get
        {
            if (this.cpuSelectedCommand == null)
                this.cpuSelectedCommand = new RelayCommand<ClassHierarchyData>(OnCPUSelected);

            return this.cpuSelectedCommand;
        }
    }

    private void OnCPUSelected(ClassHierarchyData selected)
    {
        this.SelectedItem = selected.Data;
        this.SelectedTerminalItem = (selected.Items.Count == 0) ? selected.Data : null;
    }


    private RelayCommand<string> navigateCommand;
    public RelayCommand<string> NavigateCommand
    {
        get
        {
            if (this.navigateCommand == null)
                this.navigateCommand = new RelayCommand<string>((uri) =>
                {
                    Process.Start(new ProcessStartInfo(uri));
                });

            return navigateCommand;
        }
    }

    public NewProjectViewModel()
    {
        ClassHierarchyGenerator classHierarchyGenerator = new ClassHierarchyGenerator();

        this.TotalCPUs.Add(classHierarchyGenerator.ToHierarchyData(typeof(Target)));
        this.FilterCPUs.CollectionChanged += FilterCPUs_CollectionChanged;
    }

    private void FilterCPUs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        this.FilterMode = (this.FilterCPUs.Count > 0) ? true : false;
    }
}


public class DetailType
{
    public Type Type { get; }
    public string Path { get; }

    public DetailType(Type type, string path)
    {
        Type = type;
        Path = path;
    }
}

If user input data to the TextBox for filtering then the value of the CPUSearch is changed.如果用户将数据输入到 TextBox 进行过滤,则 CPUSearch 的值会更改。

If the value of the CPUSearch is changed then be added test value into the FilterCPUs.如果 CPUSearch 的值发生变化,则将测试值添加到 FilterCPU 中。 (Note CPUSearch property) when being added value into the FilterCPUs, FilterCPUs_CollectionChanged is called and the value of the FilterMode is changed. (注意CPUSearch 属性)当被添加到FilterCPUs 中时,会调用FilterCPUs_CollectionChanged 并改变FilterMode 的值。

But the above code does not work although be changed the value of the FilterMode.但是上面的代码虽然改变了FilterMode的值却不起作用。 (works well except for functionality related to FilterMode) (除了与 FilterMode 相关的功能外,效果很好)

Why doesn't the Control switch?为什么控制开关不转?

Thanks for reading.谢谢阅读。

I solved this problem by referring WPF Showing / Hiding a control with triggers我通过参考WPF Showing / Hiding a control with triggers解决了这个问题

My XAML code updated like this and it works well.我的 XAML 代码像这样更新并且运行良好。

Thanks for your interest.谢谢你的关注。

<Grid Grid.Row="1">
    <TreeView x:Name="treeView" BorderThickness="0"
                ItemsSource="{Binding TotalCPUs}">
        <TreeView.Style>
            <Style TargetType="{x:Type TreeView}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding FilterMode}" Value="true">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding FilterMode}" Value="false">
                        <Setter Property="Visibility" Value="Visible"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TreeView.Style>

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectedItemChanged">
                <mvvm:EventToCommand Command="{Binding CPUSelectedCommand}"
                                 PassEventArgsToCommand="True"
                                 EventArgsConverter="{localConverters:SelectedItemConverter}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TreeView>

    <ListBox x:Name="listBox" BorderThickness="0"
                    ItemsSource="{Binding FilterCPUs}"
                    SelectedItem="{Binding SelectedItem}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock FontSize="8" Text="{Binding Path=Path}" Margin="0 0 0 3"/>
                    <TextBlock Text="{Binding Type.Name}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>

        <ListBox.Style>
            <Style TargetType="{x:Type ListBox}">
                <Setter Property="Background" Value="{DynamicResource CommonEnableBackgroundBrush}"/>
                <Setter Property="BorderBrush" Value="{DynamicResource CommonEnableBorderBrush}"/>
                <Setter Property="Foreground" Value="{DynamicResource CommonEnableTextBrush}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding FilterMode}" Value="true">
                        <Setter Property="Visibility" Value="Visible"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding FilterMode}" Value="false">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
    </ListBox>
</Grid>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM