我是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文件为空。
答案 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*/}
}
}
}