none
Kommunikation zwischen Frames RRS feed

  • Frage

  • Hallo

    Ich bin gerade ein bisschen an folgendem Problem am verzweifeln:

    Und zwar habe ich ein MainWindow, in welchem sich ein Frame befindet.

    Nun habe ich im MainWindow eine TextBox und im Frame eine ListBox und einen Button. Der Inhalt der Textbox soll nun von der Itemwahl in der ListBox bestimmt werden, und durch den Button bestätigt werden:

    Frame.xaml.cs

    private void SaveSelection_Click(object sender, RoutedEventArgs e)
            {
    
    string selection = (goods)ListBox1.SelectedValue.ToString();
    
            }
    

    Allerdings weiß ich nicht, wie ich diese Information in der TextBox anzeigen lassen kann. Ich habe bereits folgendes probiert:

    Frame.xaml.cs

    MainWindow frm = new MainWindow();
    frm.textBox1.Text = selection;

    Oder auch:

    Frame.xaml.cs

    MainWindow frm = new MainWindow();
    frm.TextBoxValue = selection;

    MainWindow.xaml.cs

     public string TextBoxValue
        {
            get { return textBox1.Text;} 
            set { textBox1.Text = value;}
        } 

    Ich habe auch probiert mit "Delegates" zu arbeiten. Allerdings erschien mir das Thema nicht unbedingt optimal für mein Problem geeignet und etwas kompliziert.

    Das was mir am besten für das Problem erschien, war "INotifyPropertyChanged". Allerdings bin ich nicht sehr erfahren im MVVM- Model. Daher bin ich schnell auf den Konflikt gestoßen, dass 2 unterschiedliche Fenster auf die selbe TextBox zugreifen wollen. 

    Ich denke, dass ich mit dem Problem nicht der erste bin. Könnte mir vielleicht jemand seine Best-Practice verraten, oder ein paar hilfreiche Tipps geben?

    Danke im Vorraus

    MfG


    • Bearbeitet pacours Montag, 22. August 2016 14:31 Rechtschreibung
    Montag, 22. August 2016 14:30

Antworten

  • Hi,
    Dein MainWindow und Deine Page sind 2 verschiedene Objekte, die voneinander nichts wissen.

    Damit beide die gleichen Daten verarbeiten, müssen beide Objekte auf den gleichen Datenpuffer zugreifen. Das bedeutet, dass das in der ListBox im Frame selektierte Objekt (Zeile) in einem Datenobjekt (Datenklasse, ViewModel o.ä.) gespeichert wird/ist. Die TextBox im MainWindow wird dann an die gleiche Instanz des Datenobjektes gebunden. Erreichen kann man das, indem die Klasse für das Datenobjekt im App.xaml als Ressource eingetragen wird. Sowohl MainWindow (SelectedItem der ListBox) als auch Page (Text der TextBox) nutzen als Source die gleiche Ressource.

    Hier mal eine kleine Demo mit MVVM

    App.xaml

    <Application x:Class="WpfApplication1CS.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:WpfApplication1"
                 StartupUri="Window44.xaml">
      <Application.Resources>
        <local:Window44VM x:Key="vm44"/>
      </Application.Resources>
    </Application>

    XAML:

    <Window x:Class="WpfApplication1.Window44"
            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="Window44" Height="300" Width="300">
      <Grid DataContext="{Binding Source={StaticResource vm44}}">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding SelItem.Info}" Margin="5"/>
        <Border Grid.Row="1" BorderBrush="Red" BorderThickness="3" Margin="5">
          <Frame Source="Window44Page1.xaml" Margin="5"/>
        </Border>
      </Grid>
    </Window>


    <Page x:Class="WpfApplication1.Window44Page1"
          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:WpfApplication1"
          mc:Ignorable="d" 
          d:DesignHeight="300" d:DesignWidth="300"
          Title="Window44Page1">
      <Grid DataContext="{Binding Source={StaticResource vm44}}">
        <ListBox ItemsSource="{Binding Liste}" 
                 SelectedItem="{Binding SelItem}"
                 DisplayMemberPath="Info"/>
      </Grid>
    </Page>
    

    ViewModel und Daten

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApplication1
    {
      public class Window44VM : INotifyPropertyChanged
      {
        CollectionViewSource cvs;
        public ICollectionView Liste
        {
          get
          {
            if (cvs == null)
            {
              cvs = new CollectionViewSource();
              cvs.Source = GetData();
            }
            return cvs.View;
          }
        }
    
        private object _selItem;
        public object SelItem
        {
          get { return _selItem; }
          set {
            _selItem = value;
            OnPropertyChanged();
          }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    
        private ObservableCollection<Window44Data> GetData()
        {
          ObservableCollection<Window44Data> l = new ObservableCollection<Window44Data>();
          for (int i = 1; i < 10; i++)
          {
            l.Add(new Window44Data() { Info = $"Zeile {i}" });
          }
          return l;
        }
      }
    
      public class Window44Data
      {
        public string Info { get; set; }
      }
    }
    


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.


    • Bearbeitet Peter Fleischer Montag, 22. August 2016 15:42
    • Als Antwort markiert pacours Montag, 22. August 2016 17:03
    Montag, 22. August 2016 15:08

Alle Antworten

  • Hi,
    Dein MainWindow und Deine Page sind 2 verschiedene Objekte, die voneinander nichts wissen.

    Damit beide die gleichen Daten verarbeiten, müssen beide Objekte auf den gleichen Datenpuffer zugreifen. Das bedeutet, dass das in der ListBox im Frame selektierte Objekt (Zeile) in einem Datenobjekt (Datenklasse, ViewModel o.ä.) gespeichert wird/ist. Die TextBox im MainWindow wird dann an die gleiche Instanz des Datenobjektes gebunden. Erreichen kann man das, indem die Klasse für das Datenobjekt im App.xaml als Ressource eingetragen wird. Sowohl MainWindow (SelectedItem der ListBox) als auch Page (Text der TextBox) nutzen als Source die gleiche Ressource.

    Hier mal eine kleine Demo mit MVVM

    App.xaml

    <Application x:Class="WpfApplication1CS.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:WpfApplication1"
                 StartupUri="Window44.xaml">
      <Application.Resources>
        <local:Window44VM x:Key="vm44"/>
      </Application.Resources>
    </Application>

    XAML:

    <Window x:Class="WpfApplication1.Window44"
            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="Window44" Height="300" Width="300">
      <Grid DataContext="{Binding Source={StaticResource vm44}}">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding SelItem.Info}" Margin="5"/>
        <Border Grid.Row="1" BorderBrush="Red" BorderThickness="3" Margin="5">
          <Frame Source="Window44Page1.xaml" Margin="5"/>
        </Border>
      </Grid>
    </Window>


    <Page x:Class="WpfApplication1.Window44Page1"
          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:WpfApplication1"
          mc:Ignorable="d" 
          d:DesignHeight="300" d:DesignWidth="300"
          Title="Window44Page1">
      <Grid DataContext="{Binding Source={StaticResource vm44}}">
        <ListBox ItemsSource="{Binding Liste}" 
                 SelectedItem="{Binding SelItem}"
                 DisplayMemberPath="Info"/>
      </Grid>
    </Page>
    

    ViewModel und Daten

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApplication1
    {
      public class Window44VM : INotifyPropertyChanged
      {
        CollectionViewSource cvs;
        public ICollectionView Liste
        {
          get
          {
            if (cvs == null)
            {
              cvs = new CollectionViewSource();
              cvs.Source = GetData();
            }
            return cvs.View;
          }
        }
    
        private object _selItem;
        public object SelItem
        {
          get { return _selItem; }
          set {
            _selItem = value;
            OnPropertyChanged();
          }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    
        private ObservableCollection<Window44Data> GetData()
        {
          ObservableCollection<Window44Data> l = new ObservableCollection<Window44Data>();
          for (int i = 1; i < 10; i++)
          {
            l.Add(new Window44Data() { Info = $"Zeile {i}" });
          }
          return l;
        }
      }
    
      public class Window44Data
      {
        public string Info { get; set; }
      }
    }
    


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.


    • Bearbeitet Peter Fleischer Montag, 22. August 2016 15:42
    • Als Antwort markiert pacours Montag, 22. August 2016 17:03
    Montag, 22. August 2016 15:08
  • Danke sehr! Hat mir sehr weiter geholfen.
    Montag, 22. August 2016 17:04