如何通过xaml中的DataTrigger切换控件?

问题描述 投票:0回答:1

有一个包含两个控件的窗口。一个是TreeView,另一个是ListBox。

代码如下所示。

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

现在,无论何时更改ViewModel的属性,我都希望更改控件的Visibility属性的值。 (FilterMode True =可见ListBox,FilterMode False = TreeView =可见)

为此,我如下修改了我的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>

下面是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;
    }
}

如果用户将数据输入到文本框进行过滤,则CPUSearch的值将更改。

如果CPUSearch的值被更改,则将测试值添加到FilterCPU中。 (注意CPUSearch属性)在将值添加到FilterCPU中时,将调用FilterCPUs_CollectionChanged并更改FilterMode的值。

但是,尽管更改了FilterMode的值,但是上面的代码不起作用。 (除了与FilterMode有关的功能之外,其他都可以正常工作)

为什么不控制开关?

感谢阅读。

wpf styles datatrigger
1个回答
0
投票

我通过参考WPF Showing / Hiding a control with triggers解决了这个问题

© www.soinside.com 2019 - 2024. All rights reserved.