none
Navigation von Page zu Frame RRS feed

  • Frage

  • Hallo zusammen,

    ich arbeite mich gerade in WPF C# ein und bin jetzt auf ein Problem gestoßen wobei ich nicht weiter komm.

    Ich habe ein Hauptfenster (Main) in welchem sich ein Stackpanel auf der linken Seite für die Buttons (Button1 - 6) zur Navigation befindet und ein Frame zur Darstellung der Pages (Page1 -6) welche von den Buttons angewählt werden. (eine Art Dashboard).

    Wenn ich dann den Button1 anklicke, öffne ich über (Frame.NavigationService.Navigate(Page1()); die Page1 in dem Frame, welches auch super funktioniert.

    Wenn ich aber in der Page1 (welches im Frame geöffnet ist) auf einen Button klicke um eine andere Page (z.B. Page7) finde ich keine Möglichkeit wie ich diese Page im Frame öffnen kann.

    Hab es versucht mit:

    Main _Main = new Main();

    _Main.Frame.NavigationService.Navigate(Page7());

    allerdings funktioniert das nicht.

    Hätte vieleicht jemand ne Idee oder nen Vorschlag, wie ich dies lösen kann?

    Danke schon mal.

    Sonntag, 21. Januar 2018 09:14

Antworten

  • Hi,
    Du kannst dem Frame einen anderen Content zuweisen. Hier mal eine Demo mit ViewModel, der sowohl vom Main-Window als auch von den Pages genutzt wird. Bei jedem Klick wird aber eine neue Page-Instanz erzeugt. Falls Du es anders haben willst, müsstest Du Dir die Instanzen merken, z.B. in einem Dictionary.

    XAML:

    <Window x:Class="WpfApp1CS.Window29"
            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:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window29" Height="300" Width="300">
      <Window.Resources>
        <local:Window29VM x:Key="vm"/>
        <Style TargetType="Button">
          <Setter Property="Margin" Value="5"/>
        </Style>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <StackPanel Margin="5">
          <Button Content="Page 1" Command="{Binding Cmd}" CommandParameter="Page 1"/>
          <Button Content="Page 2" Command="{Binding Cmd}" CommandParameter="Page 2"/>
        </StackPanel>
        <Frame Grid.Column="1" Margin="10" Content="{Binding ActualPage}" />
      </Grid>
    </Window>

    XAML eine Page:

    <Page x:Class="WpfApp1CS.Window29Page1"
          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:WpfApp1CS"
          mc:Ignorable="d" 
          d:DesignHeight="300" d:DesignWidth="300"
          Title="Window29Page1">
      <StackPanel>
        <Label Content="Page 1"/>
        <Button Content="Page 2" Command="{Binding Cmd}" CommandParameter="Page 2"/>
      </StackPanel>
    </Page>

    Und dazu der ViewModel:

    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace WpfApp1CS
    {
      public class Window29VM:INotifyPropertyChanged
      {
    
        public Page ActualPage { get; set; }
    
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
    
        private void CmdExec(object obj)
        {
          switch (obj.ToString())
          {
            case "Page 1":
              ActualPage = new Window29Page1();
              break;
            case "Page 2":
              ActualPage = new Window29Page2();
              break;
          }
          ActualPage.DataContext = this;
          OnPropertyChanged(nameof(ActualPage));
        }
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Sonntag, 21. Januar 2018 10:22

Alle Antworten

  • Hi,
    Du kannst dem Frame einen anderen Content zuweisen. Hier mal eine Demo mit ViewModel, der sowohl vom Main-Window als auch von den Pages genutzt wird. Bei jedem Klick wird aber eine neue Page-Instanz erzeugt. Falls Du es anders haben willst, müsstest Du Dir die Instanzen merken, z.B. in einem Dictionary.

    XAML:

    <Window x:Class="WpfApp1CS.Window29"
            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:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window29" Height="300" Width="300">
      <Window.Resources>
        <local:Window29VM x:Key="vm"/>
        <Style TargetType="Button">
          <Setter Property="Margin" Value="5"/>
        </Style>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <StackPanel Margin="5">
          <Button Content="Page 1" Command="{Binding Cmd}" CommandParameter="Page 1"/>
          <Button Content="Page 2" Command="{Binding Cmd}" CommandParameter="Page 2"/>
        </StackPanel>
        <Frame Grid.Column="1" Margin="10" Content="{Binding ActualPage}" />
      </Grid>
    </Window>

    XAML eine Page:

    <Page x:Class="WpfApp1CS.Window29Page1"
          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:WpfApp1CS"
          mc:Ignorable="d" 
          d:DesignHeight="300" d:DesignWidth="300"
          Title="Window29Page1">
      <StackPanel>
        <Label Content="Page 1"/>
        <Button Content="Page 2" Command="{Binding Cmd}" CommandParameter="Page 2"/>
      </StackPanel>
    </Page>

    Und dazu der ViewModel:

    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace WpfApp1CS
    {
      public class Window29VM:INotifyPropertyChanged
      {
    
        public Page ActualPage { get; set; }
    
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
    
        private void CmdExec(object obj)
        {
          switch (obj.ToString())
          {
            case "Page 1":
              ActualPage = new Window29Page1();
              break;
            case "Page 2":
              ActualPage = new Window29Page2();
              break;
          }
          ActualPage.DataContext = this;
          OnPropertyChanged(nameof(ActualPage));
        }
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Sonntag, 21. Januar 2018 10:22
  • Hallo,

    vielen Dank für die super schnelle Antwort. Leider hat es bei mir funktioniert.

    Ich bekomme zwar keine Fehler, aber es wird auch nichts angezeigt.

    Was ich bei meiner ersten Frage verwechselt habe ist das, dass Frame nicht in eimem Window ist sondern in einer Page. Die Pages 1-9 sind mit den Buttons auf der Page mit dem Frame zu öffnen (über NavigateService.Navigate) das Problem ist die Page 10 welche über ein Button angezigt werden soll, der sich in der Page 9 befindet.

    Hab es folgendermaßen versucht:

    <Page x:Class="Test1.Einrichten"
          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:Test1"
          mc:Ignorable="d" 
          Title="Einrichten" Height="528" Width="1013">
        <Grid>
            <StackPanel Width="145" HorizontalAlignment="Left" Margin="10,0,0,50">
                <Button x:Name="Einrichten_Start" Command="{Binding Cmd}" CommandParameter="Page_1" Content="Einrichten Start" Margin="0,30,10,0" Height="50" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Einrichten_Start_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFD6D6D6" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Setzblech_Zuführung" Command="{Binding Cmd}" CommandParameter="Page_2"  Content="Zuführung Setzblech" Margin="10,20,20,0" Height="40" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Setzblech_Zuführung_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Blister_Abführung" Command="{Binding Cmd}" CommandParameter="Page_3"  Content="Blister Abführung" Margin="10,15,20,0" Height="40" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Blister_Abführung_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Messsystem" Command="{Binding Cmd}" CommandParameter="Page_4"  Content="Messsystem" Margin="10,15,20,0" Height="40" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Messsystem_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Messtaster" Command="{Binding Cmd}" CommandParameter="Page_5"  Content="Messtaster" Visibility="Collapsed" Margin="16,10,28.6,0" Height="29" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Messtaster_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Kalibrieren" Command="{Binding Cmd}" CommandParameter="Page_6"  Content="Kalibrieren" Visibility="Collapsed" Margin="26,10,38.6,0" Height="29" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Kalibrieren_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Schwenkeinheit" Command="{Binding Cmd}" CommandParameter="Page_7"  Content="Schwenkeinheit" Margin="10,15,20,0" Height="40" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Schwenkeinheit_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
                <Button x:Name="Roboter" Command="{Binding Cmd}" CommandParameter="Page_8"  Content="Roboter" Margin="10,15,20,0" Height="40" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Roboter_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
               
            </StackPanel>
            <StackPanel Margin="10,478,858,0">
                <Button x:Name="Service" Command="{Binding Cmd}" CommandParameter="Page_9"  Content="Service" Margin="10,0,20,0" Height="40" BorderBrush="#FFCFCDCD" Foreground="Black" BorderThickness="0" Click="Service_Click">
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                    <Button.Background>
                        <LinearGradientBrush EndPoint="0,0" StartPoint="0,0">
                            <GradientStop Color="#FFF0EDED" Offset="1"/>
                        </LinearGradientBrush>
                    </Button.Background>
                </Button>
            </StackPanel>
            <Frame Margin="155,0,0,0" Content="{Binding ActualPage}"/>
        </Grid>
    </Page>
    
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace Test1
    {
        public class Frame_1 : INotifyPropertyChanged
        {
            public Page ActualPage { get; set; }
    
            public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
    
            private void CmdExec(object obj)
            {
                switch (obj.ToString())
                {
                    case "Page_1":
                        ActualPage = new Einrichten_Start();
                        break;
                    case "Page_2":
                        ActualPage = new Setzblech_Zufuehrung();
                        break;
                    case "Page_3":
                        ActualPage = new Blister_Abfuehrung();
                        break;
                    case "Page_4":
                        ActualPage = new Messsystem();
                        break;
                    case "Page_5":
                        ActualPage = new Messtaster();
                        break;
                    case "Page_6":
                        ActualPage = new Kalibrieren();
                        break;
                    case "Page_7":
                        ActualPage = new Schwenkeinheit();
                        break;
                    case "Page_8":
                        ActualPage = new Roboter();
                        break;
                    case "Page_9":
                        ActualPage = new Login_Service();
                        break;
                    case "Page_10":
                        ActualPage = new Service();
                        break;
                }
                ActualPage.DataContext = this;
                OnPropertyChanged(nameof(ActualPage));
            }
            #region  OnPropertyChanged
            public event PropertyChangedEventHandler PropertyChanged;
            private void OnPropertyChanged([CallerMemberName] string propName = "") =>
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            #endregion
        }
    
        /// <summary>
        /// Interaktionslogik für Einrichten.xaml
        /// </summary>
        public partial class Einrichten : Page
        {
            
    
            public Einrichten()
            {
                InitializeComponent();

    Noch irgendwelche Ideen?

    Sonntag, 21. Januar 2018 19:20
  • ... das Problem ist die Page 10 welche über ein Button angezigt werden soll, der sich in der Page 9 befindet.

    ...

    Noch irgendwelche Ideen?

    Aber genau das habe ich in meinem Beispiel gezeigt - Anzeige einer Page mit Button-Klick auf einer anderen Page (und auch vom Container mit dem Frame).

    Wo ist denn Dein Problem?


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 21. Januar 2018 21:05
  • Hallo,

    Ja ich weiß.

    Das Problem ist das im Frame gar nichts angezeigt wird, egal welche Page ich darin abbilden will

    Montag, 22. Januar 2018 05:18
  • Hi,
    aus Deinem Codeauszug kann ich nicht erkennen, ob Du alles so gemacht hast, wie ich es in meinem Beispiel gemacht habe. Unklar ist, wie Du den DataContext in der Einrichten-Seite gesetzt hast. Wenn es Bindungs-Probleme gibt, dann sollten diese auch im Ausgabe-Fenster beim Debugging ausgewiesen sein. Warum das bei Dir nicht so ist, kann ich aus der Ferne nicht erkennen.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Montag, 22. Januar 2018 06:09