Tipps und Tricks

Frage (554) zu , WPF:

Wie kann man Usercontrols übergreifend steuern?

Antwort:
Mit MVVM kann man im ViewModel Zustände und Werte bereitstellten, die die Oberflächenelemente abrufen. In einem UserControl wird der aktuelle Zustand angezeigt und z.B. über eine Befehlsschaltfläche "WEITER" ein neuer Zustand gesetzt. In Abhängigkeit von Zustand wird das Steuerelement entsprechend für die Anzeige modifiziert (anderes Steuerelement oder auch andere Darstellung). Es wird also nicht ein Steuerelement von einem anderen Steuerelement direkt gesteuert, sondern ein Steuerelement ändert den Inhalt der Eigenschaften im ViewModel. Über NotifyPropertyChanged wird den gebundenen Steuerelementen mitgeteilt, das sich etwas geändert hat. Die betreffenden Steuerelemente holen sich dann selbständig die Daten aus dem ViewModel.

In der nachfolgenden Demo befinden sich im MainWindow ContentControls, deren Content-Eigenschaften an Eigenschaften im ViewModel gebunden sind. Im ViewModel wird dann gesteuert, welches UserControl angezeigt wird. Das kann man im Beispiel mit "Weiter" realisieren.

Main-XAML:

[xml]

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <local:ViewModel x:Key="vm"/>
  </Window.Resources>
  <Grid DataContext="{Binding Source={StaticResource vm}}" Margin="0 50 0 0">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <ContentControl Grid.Row="0" Content="{Binding UC1}" />
    <ContentControl Grid.Row="1" Content="{Binding UC2}" />
  </Grid>
</Window>
[/xml]

ViewModel:

[c#]
using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using WpfControlLibrary1;

namespace WpfApplication1
{
  class ViewModel : INotifyPropertyChanged
  {
    public object UC1
    {
      get
      {
        return new UserControl1();
      }
    }

    private object _uc2 = new UserControl2();
    public object UC2
    {
      get
      {
        return this._uc2;
      }
    }

    public string Info { get; set; }

    public ICommand Cmd
    {
      get
      {
        return new RelayCommand(CmdExec);
      }
    }

    private bool sw;

    private void CmdExec(object obj)
    {
      if (sw)
      {
        this._uc2 = new UserControl2();
        sw = false;
      }
      else
      {
        this._uc2 = new UserControl3();
        sw = true;
      }
      OnPropertyChanged("UC2");
    }

    #region NotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    internal void OnPropertyChanged([CallerMemberName] String info = "") =>
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
    internal void OnPropertyChanged<t>(Expression<Func<t>> propertyExpression) =>
      OnPropertyChanged(propertyExpression.Name);
    #endregion
  }
}
[/c#]

Und die XAML-UserControls, die sich im Projekt WpfControlLibrary1 befinden:

[xml]
<UserControl x:Class="WpfControlLibrary1.UserControl1"
             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" 
             xmlns:local="clr-namespace:WpfControlLibrary1"
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="300">
  <Grid>
    <Border BorderBrush="Red" BorderThickness="2" Margin="5">
      <Label Content="Überschrifts-UC"/>
    </Border>
  </Grid>
</UserControl>
[/xml]

[xml]
<UserControl x:Class="WpfControlLibrary1.UserControl2"
             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" 
             xmlns:local="clr-namespace:WpfControlLibrary1"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300">
  <Border BorderBrush="Green" BorderThickness="2" Margin="5">
    <StackPanel>
      <Label Content="1. UserControl"/>
      <TextBox Text="{Binding Info}"/>
      <Button Content="Weiter" Command="{Binding Cmd}"/>
    </StackPanel>
  </Border>
</UserControl>
[/xml]

[xml]
<UserControl x:Class="WpfControlLibrary1.UserControl3"
             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" 
             xmlns:local="clr-namespace:WpfControlLibrary1"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300">
  <Border BorderBrush="Yellow" BorderThickness="5" Margin="5">
    <StackPanel>
      <Label Content="2. UserControl"/>
      <TextBox Text="{Binding Info}"/>
      <Button Content="Weiter" Command="{Binding Cmd}"/>
    </StackPanel>
  </Border>
</UserControl>
[/xml]


Stand des Beitrages: 31.05.16 13:41, zuletzt geändert: 31.05.16 13:59



Bitte wählen sie den Themenbereich aus
Bitte geben sie einen Suchbegriff ein

Die hier dargestellten Tipps und Tricks sind das Ergebnis selbst ersteller Lösungsvarianten, die für Projekte und Schulungen erarbeitet wurden.