簡體   English   中英

如何在 xaml 中通過 DataTrigger 切換控制?

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

有一個窗口由兩個控件組成。 一個是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 的屬性時,我想更改 Control 的 Visibility 屬性的值。 (FilterMode True = ListBox Visible, FilterMode False = TreeView = Visible)

為此,我修改了我的 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;
    }
}

如果用戶將數據輸入到 TextBox 進行過濾,則 CPUSearch 的值會更改。

如果 CPUSearch 的值發生變化,則將測試值添加到 FilterCPU 中。 (注意CPUSearch 屬性)當被添加到FilterCPUs 中時,會調用FilterCPUs_CollectionChanged 並改變FilterMode 的值。

但是上面的代碼雖然改變了FilterMode的值卻不起作用。 (除了與 FilterMode 相關的功能外,效果很好)

為什么控制開關不轉?

謝謝閱讀。

我通過參考WPF Showing / Hiding a control with triggers解決了這個問題

我的 XAML 代碼像這樣更新並且運行良好。

謝謝你的關注。

<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