2015-06-23 52 views
0

我是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之間進行選擇?我需要將哪些代碼添加到「選擇操作」代碼中以更改用戶控件。

的窗口

<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

所有你需要做的是處理你的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個用戶控件,其中N是可變的,你可以創建字典,包含所有控件:

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

不會增加新的控制對每個選擇在數據網格消耗內存爲他們之間的用戶切換?理想情況下,它應該在它們之間切換 – JME

+0

JME,GC在調用dgRoot.Children.Clear()時應該收集不需要的對象。但是如果你不想在每個選擇中創建新的控件,請查看更改和我的其他答案。 – VMaleev