更改用户对列表选择的控制

本文关键字:选择 控制 列表 用户 | 更新日期: 2023-09-27 17:59:07

我是WPF的新手,并试图在选择相应的listviewitem时动态显示用户控件。我已经看了以下问题

WPF:根据相应的ViewModels(MVVM)切换UserControls

使用WPF/MVVM 在运行时动态更改UserControl内容

动态用户控制更改-WPF

所有的问题都提到了MVVM,我不认为我在使用它,或者如果我在使用,那是在不知不觉中。

为了更好地解释我正在尝试做什么,我在左侧有一个列表视图的窗口,在右侧,我想根据列表中的哪个项目被选择来动态显示用户控件。

要在用户控件1和用户控件2之间进行选择,我需要向XAML添加什么?要更改用户控件,我需要在"选择时操作"代码中添加哪些代码。

窗口

<Window x:Class="Manager.ProfileWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="Edit Profile" Height="500" Width="700">
    <Grid Background="WhiteSmoke">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" MinWidth="150" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="3*" MinWidth="300" />
        </Grid.ColumnDefinitions>
        <DockPanel>
            <Border DockPanel.Dock="Top" Height="30" Margin="2">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF5476F8" Offset="0"/>
                        <GradientStop Color="#FF001C87" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>
                <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" 
            Text=" Profile Settings" FontSize="16" FontWeight="Bold" Foreground="White" Grid.Row="1"/>
            </Border>
            <ListView Margin="2" x:Name="SettingsList" DockPanel.Dock="Top" ItemsSource="{Binding Settings}"></ListView>
        </DockPanel>
        <GridSplitter Grid.Column="1" Grid.Row="0" Width="2" HorizontalAlignment="Stretch" ResizeDirection="Columns"/>
    </Grid>
</Window>

用户控制1

<UserControl x:Class="Manager.SomeSettings"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Border VerticalAlignment="Top" Height="30" Margin="2">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF5476F8" Offset="0"/>
                    <GradientStop Color="#FF001C87" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background>
            <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" 
            Text="Some Settings" Padding="5,0,0,0" FontSize="16" FontWeight="Bold" Foreground="White" Grid.Row="1"/>
        </Border>
    </Grid>
</UserControl>

用户控制2

<UserControl x:Class="Manager.LocationSettings"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Border VerticalAlignment="Top" Height="30" Margin="2">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF5476F8" Offset="0"/>
                    <GradientStop Color="#FF001C87" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background>
            <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" 
            Text="Location Settings" Padding="5,0,0,0" FontSize="16" FontWeight="Bold" Foreground="White" Grid.Row="1"/>
        </Border>
    </Grid>
</UserControl>

用户控件的*.xaml.cs文件为空。

更改用户对列表选择的控制

您所需要做的就是处理ListView对象的SelectionChanged:

<Window x:Class="Manager.ProfileWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="Edit Profile" Height="500" Width="700">
    <Grid Background="WhiteSmoke" Name="dgRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" MinWidth="150" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="3*" MinWidth="300" />
        </Grid.ColumnDefinitions>
    <DockPanel>
        <Border DockPanel.Dock="Top" Height="30" Margin="2">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF5476F8" Offset="0"/>
                    <GradientStop Color="#FF001C87" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background>
            <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center"
                       Text=" Profile Settings" FontSize="16" FontWeight="Bold" Foreground="White" Grid.Row="1"/>
        </Border>
        <ListView x:Name="SettingsList" 
                  Margin="2" 
                  DockPanel.Dock="Top" 
                  ItemsSource="{Binding Settings}"
                  SelectionChanged="OnSelectionChanged"></ListView>
    </DockPanel>
    <GridSplitter Grid.Column="1" Grid.Row="0" Width="2" HorizontalAlignment="Stretch" ResizeDirection="Columns"/>
</Grid>

我还将你的根命名为Grid。下面是代码:

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
            dgRoot.Children.Clear();
            UserControl control = null;
            if (<your_condition>)
            {
                control = new UserControl1();
            }
            else
            {
                control = new UserControl2();
            }
            control.SetValue(Grid.ColumnProperty, 2);
            this.dgRoot.Children.Add(control);
    }

添加:如果您不确定GC会收集不需要的对象,您可以将这些控件添加为类的字段,并在构造函数中初始化它们:

public partial class ProfileWindow : Window
{
    UserControl control1, control2;
    // or if you want the exact types:
    // UserControl1 control1;
    // UserControl2 control2;
    public ProfileWindow()
    {
        control1 = new UserControl1();
        control2 = new UserControl2();
    }
    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
            if (<your_condition>) //then you want to add UserControl1 instance
            {
                if (!dgRoot.Children.Contains(control1))
                {
                    dgRoot.Children.Clear();  
                    control1.SetValue(Grid.ColumnProperty, 2);
                    this.dgRoot.Children.Add(control1);                      
                }
            }
            else //else you want to add UserControl2 instance
            {
                if (!dgRoot.Children.Contains(control2))
                {
                    dgRoot.Children.Clear();  
                    control2.SetValue(Grid.ColumnProperty, 2);
                    this.dgRoot.Children.Add(control2);                      
                }
            }
    }
}

附加2:你可以走得更远。如果你有N个UserControls,其中N是可变的,你可以创建包含所有控件的Dictionary:

public partial class ProfileWindow : Window
{
    private Dictionary<SettingsObject, UserControl> SettingsControls;
    public ProfileWindow()
    {
        SettingsControls = new Dictionary<SettingsObject, UserControl>();
        SettingsControls.Add(<your_setting>, new UserControl1());
        SettingsControls.Add(<your_another_setting>, new UserControl2());
        // and you can add any controls you want.
        // in this example SettingsObject is type of items that are in the ListView.
        // so, if your "Settings" object contains only strings, your dictionary can be Dictionary<string, UserControl>.
        // if SettingsObject is custom object, you have to override GetHash() and Equals() methods for it
    }
    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var item = SettingsList.SelectedItem is SettingsObject;
        if (item == null) return;
        if (SettingsControls.ContainsKey(item) && !dgRoot.Children.Contains(SettingsControls[item]))
        {
            dgRoot.Children.Clear();
            SettingsControls[item].SetValue(Grid.ColumnProperty, 2);
            dgRoot.Children.Add(SettingsControls[item]);
        }
        else
        { /*handle it if you want*/}
    }
}
}