简体   繁体   中英

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.

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. (FilterMode True = ListBox Visible, FilterMode False = TreeView = Visible)

To this, I modified my XAML code as below.

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

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.

If the value of the CPUSearch is changed then be added test value into the FilterCPUs. (Note CPUSearch property) when being added value into the FilterCPUs, FilterCPUs_CollectionChanged is called and the value of the FilterMode is changed.

But the above code does not work although be changed the value of the FilterMode. (works well except for functionality related to FilterMode)

Why doesn't the Control switch?

Thanks for reading.

I solved this problem by referring WPF Showing / Hiding a control with triggers

My XAML code updated like this and it works well.

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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