2016-03-03 4 views
1

У меня есть файл XAML, который имеет две вещи,Пользовательские привязки данных к более чем одна вещь WPF C#

  1. в Combo Box

  2. StackPanel

Как я сделайте так, чтобы смена в поле со списком автоматически заставила панель стека переключиться с одной панели стека на другую стекную панель.

Мой COMBOBOX что-то вроде

<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 для каждого типа подключения. Просто укажите DataTemplates с целевым типом каждой ViewModel, а после этого используйте ContentControl, с свойством content привязанным свойством CurrentConnection вашей основной модели представления, которое будет зависеть от выделени SelectedValue из combotox ConnectionType.

ОБНОВЛЕНИЕ
Исходный код, чтобы проиллюстрировать решение:

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