2016-03-03 62 views
1

我有有兩件事情XAML文件,自定義數據綁定到一個以上的東西WPF C#

  1. 組合框

  2. 一個StackPanel

如何我使組合框中的更改將自動使堆疊面板從一個堆疊面板切換到另一個堆疊面板。

我的組合框是一樣的東西

<ComboBox x:Name="MCbConnect" SelectedIndex="{Binding EnConnectionType}" Loaded="m_cbConnect_Loaded" SelectionChanged="m_cbConnect_SelectionChanged" Width="100"></ComboBox> 

其中EnConnectionType是一個屬性這樣

private ConnectionType _enConnectionType; 
    public ConnectionType EnConnectionType 
    { 
     get { return _enConnectionType; } 
     set { SetProperty(ref _enConnectionType, value, "EnConnectionType"); } 
    } 

而且ConnectionType是

public enum ConnectionType { Rs232 = 0, Can = 1, Ethernet = 2 }; 

所以我已經實現INotifyChanged接口已經在這裏。但我不知道如何綁定這個數據與一個stackpanel容器,這將允許我在後臺自動切換到不同的堆疊面板視圖。一個XAML的

的例子,我想切換到的

<GroupBox x:Class="Gui.CtrlCommSocketSettings" 
    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:src="clr-namespace:Akribis.Gui"    
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    Header="Comm Settings" 
    mc:Ignorable="d" 
    d:DesignHeight="80" d:DesignWidth="300"> 

<Grid Height="70" VerticalAlignment="Top"> 
    <Grid.Resources> 
     <Style TargetType="TextBlock"> 
      <Setter Property="HorizontalAlignment" Value="Right"/> 
      <Setter Property="VerticalAlignment" Value="Center"/> 
      <Setter Property="Margin" Value="0,0,3,0"/> 
     </Style> 

     <Style TargetType="TextBox"> 
      <Setter Property="Width" Value="120"/> 
      <Setter Property="Margin" Value="0,1"/> 
     </Style> 

     <Style TargetType="CheckBox"> 
      <Setter Property="Margin" Value="0,4"/> 
     </Style> 
    </Grid.Resources> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto"/> 
     <ColumnDefinition Width="Auto"/> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 

    <TextBlock Grid.Row="0" Text="Server:" Name="MTextBlockServer"/> 
    <TextBlock Grid.Row="1" Text="Port:"/> 

    <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Server}" Name="MTextBoxServer"/> 
    <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Port}"/> 
</Grid> 

與一些CS文件中像

namespace Gui 
{ 
    public partial class CtrlCommSocketSettings 
    { 
     public CtrlCommSocketSettings() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

我不想因爲我知道要做到這一點編程我想避免模型和視圖之間的耦合。

的是什麼,我不想這樣做,但目前所面對的

例如: 主XAML,我有一個空的StackPanel

<StackPanel Orientation="Vertical" Name="MCtrlCommSettings"></StackPanel> 

,我很明確地做這樣的事情

加入到這個StackPanel中
MCtrlCommSettings.Children.Clear(); 
MCtrlCommSettings.Children.Add(_serverCtrlCommSettings); 

我該如何去做這個自動?就像InotifyChanges將如何自動在視圖和模型之間更新一樣。任何建議都會受到歡迎。

在線閱讀,看來我需要實現某種形式的可觀察名單

回答

1

我建議一起去的DataTemplates和獨立的ViewModels爲每個連接類型。只需在每個ViewModel的目標類型中指定DataTemplates,然後使用ContentControl,並使用內容屬性綁定您的主視圖模型的CurrentConnection屬性,這取決於ConnectionType組合框的SelectedValue。

UPDATE
源代碼來說明該解決方案:

XAML

<Window x:Class="MVVMExample.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:MVVMExample" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="250" Width="425"> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type local:Rs232ConnectionViewModel}"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
       </Grid.ColumnDefinitions> 

       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 

       <TextBlock Grid.Row="0" Text="Rs232Port:" /> 

       <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Rs232Port}" /> 
      </Grid> 

     </DataTemplate> 

     <DataTemplate DataType="{x:Type local:CanConnectionViewModel}"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
       </Grid.ColumnDefinitions> 

       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 

       <TextBlock Grid.Row="0" Text="CanParam:" /> 

       <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding CanParam}" /> 
      </Grid> 
     </DataTemplate> 

     <DataTemplate DataType="{x:Type local:EthernetConnectionViewModel}"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
       </Grid.ColumnDefinitions> 

       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 

       <TextBlock Grid.Row="0" Text="Server:" /> 
       <TextBlock Grid.Row="1" Text="Port:"/> 

       <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding EthernetServer}" /> 
       <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding EthernetPort}"/> 
      </Grid> 
     </DataTemplate> 
    </Window.Resources> 
    <Window.DataContext> 
     <local:MainWindowViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="30"/> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 
     <ComboBox x:Name="MCbConnect" SelectedValue="{Binding CurrentConnectionType}" ItemsSource="{Binding ConnectionTypes}"> 
      <ComboBox.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding ConnectionType}" /> 
       </DataTemplate> 
      </ComboBox.ItemTemplate> 
     </ComboBox> 

     <ContentControl Grid.Row="1" Content="{Binding CurrentConnectionType}" /> 


    </Grid> 
</Window> 

C#

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
} 

public class MainWindowViewModel : INotifyPropertyChanged 
{ 
    ObservableCollection<ConnectionTypeViewModel> _connectionTypes; 

    public ObservableCollection<ConnectionTypeViewModel> ConnectionTypes 
    { 
     get { return _connectionTypes; } 
     private set { _connectionTypes = value; } 
    } 

    public MainWindowViewModel() 
    { 
     ConnectionTypes = new ObservableCollection<ConnectionTypeViewModel>(new ConnectionTypeViewModel[] 
     { 
      new Rs232ConnectionViewModel() { ConnectionType = ConnectionType.Rs232, Rs232Port="COM1"}, 
      new CanConnectionViewModel() { ConnectionType = ConnectionType.Can}, 
      new EthernetConnectionViewModel() { ConnectionType = ConnectionType.Ethernet, EthernetServer="tcp://xxxx"}, 
     }); 

     CurrentConnectionType = ConnectionTypes[2]; 
    } 

    private ConnectionTypeViewModel _currentConnectionType; 
    public ConnectionTypeViewModel CurrentConnectionType 
    { 
     get { return _currentConnectionType; } 
     set 
     { 
      _currentConnectionType = value; 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentConnectionType))); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 


public class ConnectionTypeViewModel : INotifyPropertyChanged 
{ 
    private ConnectionType _connectionTypeName; 

    public ConnectionType ConnectionType 
    { 
     get { return _connectionTypeName; } 
     set { _connectionTypeName = value; OnPropertyChanged(); } 
    } 

    protected void OnPropertyChanged([CallerMemberName] string name = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 


public class Rs232ConnectionViewModel : ConnectionTypeViewModel 
{ 
    private string _rs232Port; 

    public string Rs232Port 
    { 
     get { return _rs232Port; } 
     set { _rs232Port = value; OnPropertyChanged(); } 
    } 
} 


public class CanConnectionViewModel : ConnectionTypeViewModel 
{ 
    private string _canParam; 
    public string CanParam 
    { 
     get { return _canParam; } 
     set { _canParam = value; OnPropertyChanged(); } 
    } 
} 

public class EthernetConnectionViewModel : ConnectionTypeViewModel 
{ 
    private string _ethernetServer; 
    public string EthernetServer 
    { 
     get { return _ethernetServer; } 
     set { _ethernetServer = value; OnPropertyChanged(); } 
    } 

    private string _ethernetPort; 
    public string EthernetPort 
    { 
     get { return _ethernetPort; } 
     set { _ethernetPort = value; OnPropertyChanged(); } 
    } 
} 

public enum ConnectionType { Rs232 = 0, Can = 1, Ethernet = 2 }; 
+1

冠軍。非常感謝你,它完美的作品 – CJC