更改列表选择的用户控制

时间:2015-06-23 15:55:57

标签: c# wpf xaml

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

WPF: switching UserControls depending on corresponding ViewModels (MVVM)

Dynamically changing UserControl content at run time with WPF/MVVM

Dynamic user control change - WPF

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

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

我需要添加到XAML以在用户控件1和用户控件2之间进行选择?我需要在“on selection action”代码中添加哪些代码来更改用户控件。

窗口

<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文件为空。

1 个答案:

答案 0 :(得分:1)

您需要做的就是处理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>

我还命名了你的根网格。这里有代码:

    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*/}
    }
}
}