none
UserControl aus UserControl öffnen WPF RRS feed

  • Frage

  • hallo,

    ich würde gerne aus meiner UserControl (in meinem MainWindows als Child geöffnete Suchmaske), beim Ausführen der Suche  diese UserControl schließen und im gleichen Feld des MainWindows eine andere UserControl (mit den Suchergebnissen) anzeigen lassen.

    Allerdings schaffe ich es nicht aus einer UserControl auf die Children meines Grids(x:Name="UserControls") im MainWindows zuzugreifen. 

    Meine Frage: Wie kann in meinem searchUserControl mit einem Button Click diese geschlossen werden und im gleichen Fenster die searchResultsUserControl mit den aus der searchUserControl übergebenen Parametern geöffnet werden?

    XAML Code MainWindow:

    ...

    private void menuHomeButton_Click(object sender, RoutedEventArgs e)
            {

                // Clear the userControls Grid
                userControls.Children.Clear();

                // Add the resultTableUserControl to the userControls Grid
                userControls.Children.Add(new searchUserControl
                {
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    VerticalAlignment = VerticalAlignment.Stretch
                });
            }

    ...

    Da ich noch ziemlich neu in der Thematik bin und derzeit an diesem Problem am Verzweifeln bin, wäre ich über eine Antwort sehr Dankbar.

    Vielen Dank im Voraus für eure Hilfe

    Mittwoch, 11. März 2020 10:09

Antworten

  • Hi Tobi,
    in einem DataGrid hat eine Anzeige in einer Zeile des DataGrids als Datenquelle nicht den gesamten ViewModel, sondern das angezeigte Datenobjekt. Da bedeutet, dass "Command" entweder an eine Eigenschaft in Datenobjekt gebunden werden muss, oder über Source auf die Instanz das (übergeordneten) ViewModels zu verweisen ist.

    Hier mal eine Demo:

    XAML Window

    <Window x:Class="WpfApp1.Window06"
            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:WpfApp06"
            mc:Ignorable="d"
            Title="Window06" Height="450" Width="800">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid ItemsSource="{Binding View}" AutoGenerateColumns="False" IsReadOnly="True">
          <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
            <DataGridTextColumn Header="Info" Binding="{Binding Info}"/>
            <DataGridTemplateColumn>
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <StackPanel>
                    <Button Content="Search" Command="{Binding Cmd, Source={StaticResource vm}}" CommandParameter="{Binding}"/>
                  </StackPanel>
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
          </DataGrid.Columns>
        </DataGrid>
        <ContentControl Grid.Column="1" Content="{Binding Detail}"/>
      </Grid>
    </Window>

    XAML 1. UserControl:

    <UserControl x:Class="WpfApp1.Window06UC1"
                 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:WpfApp1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <StackPanel>
        <Border BorderBrush="Red" BorderThickness="3" Margin="5">
          <StackPanel>
            <Label Content="UserControl 1" Margin="5"/>
            <TextBox Margin="5" Text="{Binding Info}"/>
            <Button Content="Close UserControl 1" Command="{Binding CmdDetail}" CommandParameter="StartUC2" Margin="5"/>
          </StackPanel>
        </Border>
      </StackPanel>
    </UserControl>

    XAML 2. UserControl:

    <UserControl x:Class="WpfApp1.Window06UC2"
                 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:WpfApp1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <StackPanel>
        <Border BorderBrush="Green" BorderThickness="3" Margin="5">
          <StackPanel>
            <Label Content="UserControl 2" Margin="5"/>
            <TextBox Margin="5" Text="{Binding Info}"/>
            <Button Content="Close UserControl 2" Command="{Binding CmdDetail}" CommandParameter="StartUC1" Margin="5"/>
          </StackPanel>
        </Border>
      </StackPanel>
    </UserControl>

    Und die Klassen:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp06
    {
      public class ViewModel : INotifyPropertyChanged
      {
        public ViewModel()
        {
          ObservableCollection<Data> col = new ObservableCollection<Data>();
          for (int i = 1; i < 10; i++) col.Add(new Data() { ID = i, Info = $"Row {i}" });
          col.CollectionChanged += (sender, e) => { OnPropertyChanged(nameof(Cmd)); };
          cvs.Source = col;
        }
        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View { get => cvs.View; }
    
        public UserControl Detail { get; set; }
    
        public ICommand Cmd { get => new RelayCommand(CmdExec); }
        private void CmdExec(Object obj)
        {
          var d = obj as Data;
          if (d == null) return;
          d.CmdDetail = new RelayCommand(CmdExecDetail);
          Detail = new WpfApp1.Window06UC1() { DataContext = d };
          OnPropertyChanged(nameof(Detail));
        }
    
        public ICommand CmdDetail { get => new RelayCommand(CmdExecDetail); }
    
        private void CmdExecDetail(Object obj)
        {
          if (obj != null)
          {
            switch (obj.ToString())
            {
              case "StartUC1":
                Detail = null;
                break;
              case "StartUC2":
                Detail = new WpfApp1.Window06UC2() { DataContext = Detail.DataContext };
                break;
              default:
                break;
            }
            OnPropertyChanged(nameof(Detail));
          }
        }
    
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        internal void OnPropertyChanged([CallerMemberName] string propName = "") =>
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
    
      public partial class Data
      {
        public ICommand CmdDetail { get; set; }
      }
    
      public class RelayCommand : ICommand
      {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _action;
        public RelayCommand(Action<object> action) { _action = action; _canExecute = null; }
        public RelayCommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }
        public void Execute(object o) => _action(o);
        public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);
        public event EventHandler CanExecuteChanged
        {
          add { CommandManager.RequerySuggested += value; }
          remove { CommandManager.RequerySuggested -= value; }
        }
      }
    
      public partial class Data
      {
        public int ID { get; set; }
        public string Info { get; set; }
      }
    
    }


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks



    • Bearbeitet Peter Fleischer Donnerstag, 12. März 2020 09:27
    • Als Antwort markiert TobiP30 Sonntag, 22. März 2020 16:43
    Donnerstag, 12. März 2020 08:51

Alle Antworten

  • Hi Tobi,
    wenn sowohl das Hauptfenster als auch die UserControls die gleiche Instanz eines ViewModels nutzen, können alle die gleichen Eigenschaften binden und nutzen damit die gleichen Werte. Hier mal eine Demo:

    XAML Hauptfenster:

    <Window x:Class="WpfApp1.Window04"
            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:WpfApp04"
            mc:Ignorable="d"
            Title="Window04" Height="450" Width="800">
      <Window.DataContext>
        <local:ViewModel/>
      </Window.DataContext>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0">
          <Button Content="Start Child Window" Command="{Binding Cmd}" CommandParameter="StartUC1" Margin="5"/>
          <Label Content="{Binding Info}"/>
        </StackPanel>
        <ContentControl Grid.Row="1" Content="{Binding Detail}"/>
      </Grid>
    </Window>

    XAML UserControl1:

    <UserControl x:Class="WpfApp1.Window04UC1"
                 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:WpfApp1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <StackPanel>
        <Border BorderBrush="Red" BorderThickness="3" Margin="5">
          <StackPanel>
            <Label Content="UserControl 1" Margin="5"/>
            <TextBox Margin="5" Text="{Binding Info}"/>
            <Button Content="Close UserControl 1" Command="{Binding Cmd}" CommandParameter="StartUC2" Margin="5"/>
          </StackPanel>
        </Border>
      </StackPanel>
    </UserControl>

    XAML UserControl2

    <UserControl x:Class="WpfApp1.Window04UC2"
                 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:WpfApp1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <StackPanel>
        <Border BorderBrush="Green" BorderThickness="3" Margin="5">
          <StackPanel>
            <Label Content="UserControl 2" Margin="5"/>
            <TextBox Margin="5" Text="{Binding Info}"/>
            <Button Content="Close UserControl 2" Command="{Binding Cmd}" CommandParameter="StartUC1" Margin="5"/>
          </StackPanel>
        </Border>
      </StackPanel>
    </UserControl>

    Und dazu ViewModel und Klassen:

    using System;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace WpfApp04
    {
      public class ViewModel : INotifyPropertyChanged
      {
        private string _info = "<empty>";
        public string Info { get { return this._info; } set { this._info = value; OnPropertyChanged(); } }
        public UserControl Detail { get; set; }
    
        public ICommand Cmd { get => new RelayCommand(CmdExec); } // property for binding Button
        private void CmdExec(object obj) // execute when clicking Button
        {
          switch (obj.ToString())
          {
            case "StartUC1":
              Detail = new WpfApp1.Window04UC1();
              break;
            case "StartUC2":
              Detail = new WpfApp1.Window04UC2();
              break;
            default:
              break;
          }
          OnPropertyChanged(nameof(Detail));
        }
    
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        internal void OnPropertyChanged([CallerMemberName] string propName = "") =>
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
    
      }
    
      public class RelayCommand : ICommand
      {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _action;
        public RelayCommand(Action<object> action) { _action = action; _canExecute = null; }
        public RelayCommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }
        public void Execute(object o) => _action(o);
        public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);
        public event EventHandler CanExecuteChanged
        {
          add { CommandManager.RequerySuggested += value; }
          remove { CommandManager.RequerySuggested -= value; }
        }
      }
    
    }


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    • Als Antwort markiert TobiP30 Mittwoch, 11. März 2020 12:20
    • Tag als Antwort aufgehoben TobiP30 Mittwoch, 11. März 2020 16:39
    Mittwoch, 11. März 2020 10:53
  • Vielen Dank für die schnelle Antwort.

    Ich habe dies nun implementiert jedoch öffnet sich zwar die searchUserControl() dadurch, allerdings lässt sich die resultsUserControl nicht aus der searchUserControl() öffnen.

    Der Button in der searchUserControl() befindet sich in einem DataGrid, anscheinend liegt der Fehler dort, da es funktioniert wenn der Button außerhalb des DataGrids liegt...

    Wie kann dies auch mit dem Button innerhalb des DataGridTemplateColumns zum laufen gebracht werden?

    <DataGridTemplateColumn>
       <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
            <StackPanel>
                <Button Content="Search" Command="{Binding Cmd}" CommandParameter="ViewSQLContent"/>               
             </StackPanel>
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>

    private void CmdExec(object obj) // execute when clicking Button
            {
                switch (obj.ToString())
                {
                    case "ViewSearchMask":
                        Detail = new searchUserControl();
                        break;
                    case "ViewSQLContent":
                        Detail = new resultsUserControl();
                        break;
                    case "OpenSearchMask":
                        Detail = new searchUserControl();
                        break;
                        
                    default:
                        break;
                }
                OnPropertyChanged(nameof(Detail));
            }







    • Bearbeitet TobiP30 Mittwoch, 11. März 2020 15:23
    Mittwoch, 11. März 2020 14:18
  • Hi Tobi,
    in einem DataGrid hat eine Anzeige in einer Zeile des DataGrids als Datenquelle nicht den gesamten ViewModel, sondern das angezeigte Datenobjekt. Da bedeutet, dass "Command" entweder an eine Eigenschaft in Datenobjekt gebunden werden muss, oder über Source auf die Instanz das (übergeordneten) ViewModels zu verweisen ist.

    Hier mal eine Demo:

    XAML Window

    <Window x:Class="WpfApp1.Window06"
            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:WpfApp06"
            mc:Ignorable="d"
            Title="Window06" Height="450" Width="800">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid ItemsSource="{Binding View}" AutoGenerateColumns="False" IsReadOnly="True">
          <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
            <DataGridTextColumn Header="Info" Binding="{Binding Info}"/>
            <DataGridTemplateColumn>
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <StackPanel>
                    <Button Content="Search" Command="{Binding Cmd, Source={StaticResource vm}}" CommandParameter="{Binding}"/>
                  </StackPanel>
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
          </DataGrid.Columns>
        </DataGrid>
        <ContentControl Grid.Column="1" Content="{Binding Detail}"/>
      </Grid>
    </Window>

    XAML 1. UserControl:

    <UserControl x:Class="WpfApp1.Window06UC1"
                 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:WpfApp1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <StackPanel>
        <Border BorderBrush="Red" BorderThickness="3" Margin="5">
          <StackPanel>
            <Label Content="UserControl 1" Margin="5"/>
            <TextBox Margin="5" Text="{Binding Info}"/>
            <Button Content="Close UserControl 1" Command="{Binding CmdDetail}" CommandParameter="StartUC2" Margin="5"/>
          </StackPanel>
        </Border>
      </StackPanel>
    </UserControl>

    XAML 2. UserControl:

    <UserControl x:Class="WpfApp1.Window06UC2"
                 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:WpfApp1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <StackPanel>
        <Border BorderBrush="Green" BorderThickness="3" Margin="5">
          <StackPanel>
            <Label Content="UserControl 2" Margin="5"/>
            <TextBox Margin="5" Text="{Binding Info}"/>
            <Button Content="Close UserControl 2" Command="{Binding CmdDetail}" CommandParameter="StartUC1" Margin="5"/>
          </StackPanel>
        </Border>
      </StackPanel>
    </UserControl>

    Und die Klassen:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp06
    {
      public class ViewModel : INotifyPropertyChanged
      {
        public ViewModel()
        {
          ObservableCollection<Data> col = new ObservableCollection<Data>();
          for (int i = 1; i < 10; i++) col.Add(new Data() { ID = i, Info = $"Row {i}" });
          col.CollectionChanged += (sender, e) => { OnPropertyChanged(nameof(Cmd)); };
          cvs.Source = col;
        }
        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View { get => cvs.View; }
    
        public UserControl Detail { get; set; }
    
        public ICommand Cmd { get => new RelayCommand(CmdExec); }
        private void CmdExec(Object obj)
        {
          var d = obj as Data;
          if (d == null) return;
          d.CmdDetail = new RelayCommand(CmdExecDetail);
          Detail = new WpfApp1.Window06UC1() { DataContext = d };
          OnPropertyChanged(nameof(Detail));
        }
    
        public ICommand CmdDetail { get => new RelayCommand(CmdExecDetail); }
    
        private void CmdExecDetail(Object obj)
        {
          if (obj != null)
          {
            switch (obj.ToString())
            {
              case "StartUC1":
                Detail = null;
                break;
              case "StartUC2":
                Detail = new WpfApp1.Window06UC2() { DataContext = Detail.DataContext };
                break;
              default:
                break;
            }
            OnPropertyChanged(nameof(Detail));
          }
        }
    
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        internal void OnPropertyChanged([CallerMemberName] string propName = "") =>
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
    
      public partial class Data
      {
        public ICommand CmdDetail { get; set; }
      }
    
      public class RelayCommand : ICommand
      {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _action;
        public RelayCommand(Action<object> action) { _action = action; _canExecute = null; }
        public RelayCommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }
        public void Execute(object o) => _action(o);
        public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);
        public event EventHandler CanExecuteChanged
        {
          add { CommandManager.RequerySuggested += value; }
          remove { CommandManager.RequerySuggested -= value; }
        }
      }
    
      public partial class Data
      {
        public int ID { get; set; }
        public string Info { get; set; }
      }
    
    }


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks



    • Bearbeitet Peter Fleischer Donnerstag, 12. März 2020 09:27
    • Als Antwort markiert TobiP30 Sonntag, 22. März 2020 16:43
    Donnerstag, 12. März 2020 08:51
  • Hi Peter,

    Ja das habe ich mir schon gedacht ); 

    Welche explizite Möglichkeit gibt es denn aus dem DataGrid an das ViewModel zu verweisen?

    Die Anwendung muss diese Woche noch lauffähig gemacht werden und wäre über eine Umsetzungsmöglichkeit zur Lösung des Problems sehr Dankbar(;

    Vielen Dank im Voraus

    Mit freundlichen Grüßen

    Tobias

    Donnerstag, 12. März 2020 09:04
  • Hi Tobi,
    ich habe zum letzten Post noch den Code einer Demo hinzugefügt. Schau dir das mal an und frage etwas detaillierter (bezüglich Bedientechnologie), da es da dank WPF sehr viele Möglichkeiten gibt.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 12. März 2020 09:32
  • Hi Tobi,
    ich habe zu deine Frage im englisch sprachigen Forum geantwortet, schau mal dort.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Freitag, 13. März 2020 08:01
  • Hallo Peter,

    Wenn ich den Button in meinem DataGrid im UserControl1 klicke, wird das UserControl2 einfach nicht geöffnet!, obwohl das Programm im CmdExec in den korrekten Case springt und Detail = new UserControls.EditUC() ausgeführt wird. Wenn ich den Inhalt (mit Datagrid) jedoch in das MainWindow code, und von dort aus den Buttonclick im Datagrid ausführe öffnet sich das UserControl2, obwohl der Code identisch ist... Das Datagrid soll jedoch im UserControl2 sein.

    UserControl2:

    <UserControl x:Class="FirewallDBGUI.UserControls.DBContentUC" 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:FirewallDBGUI.UserControls" xmlns:ViewModels="clr-namespace:FirewallDBGUI.ViewModels" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Resources> <ViewModels:ViewModel1 x:Key="vm"/>

    ... </UserControl.Resources> <Grid DataContext="{StaticResource vm}"> <DockPanel> <DataGrid x:Name="myDataGrid" x:FieldModifier="public" AutoGenerateColumns="False" HorizontalScrollBarVisibility="Auto" ColumnWidth="*" GridLinesVisibility="Horizontal" HorizontalGridLinesBrush="Transparent" RowStyle="{StaticResource RowStyleWithAlternation}"> <DataGrid.Columns > <DataGridTextColumn Header="Antrag_ID" IsReadOnly="True" Width="100" Binding="{Binding Antrag_ID}" MinWidth="80"/> <DataGridTextColumn Header="Titel" IsReadOnly="True" Width="130" Binding="{Binding Titel}" MinWidth="100"/> <DataGridTextColumn Header="InPro_ID" IsReadOnly="True" Width="200" Binding="{Binding InPro_ID}" MinWidth="140"/> ... <DataGridTextColumn Header="Beschreibung" IsReadOnly="True" Width="200" Binding="{Binding Beschreibung}" MinWidth="200"/> <DataGridTemplateColumn MinWidth="70"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel> <!-- <Button x:Name="insertBtn" Content="Insert" Click="insertBtn_Click" /> --> <Button x:Name="updateBtn" Content="Update" Command="{Binding Cmd, Source={StaticResource vm}}" CommandParameter="ViewEditUC"/> <!-- <Button x:Name="deleteBtn" Content="Delete" Click="deleteBtn_Click" /> --> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </DockPanel> </Grid> </UserControl>


    Woran kann dies liegen?! 



    • Bearbeitet TobiP30 Samstag, 14. März 2020 21:59
    Samstag, 14. März 2020 21:56
  • Hi Tobi,
    in Deinem DBContentUC deklarierst Du eine Ressource (Key=vm), von der dann implizit eine Instanz erzeugt wird, im Grid, die dann auch im Button des DataGridTemplateColumn genutzt wird. Ich vermute, dass Du im entsprechenden ViewModel kein Singleton implementiert hast und du deshalb mit unterschiedlichen Instanzen arbeitest. Das solltest du als erstes prüfen. Das geht ganz schnell, indem du im Konstruktor des ViewModels den Aufruf protokollierst, ggf. mit Ausgabe des Stacks. Wenn der Konstruktor mehrmals aufgerufen wird, gibt es mehrere Instanzen. Und, wenn dann kein singleton pattern implementiert ist, kann folgendes passieren:

    - Die erste Instanz wird für die Bindung im Main bzw. ersten UserControl genutzt;
    - die zweite Instanz wird im DBContentUC genutzt;
    - Änderungen in der zweiten Instanz haben keine Auswirkungen auf die Werte in der ersten Instanz.

    Ein einfache Lösung könnte erst einmal z.B. sein, die Ressource {ViewModel1 x:Key="vm"} im App.xaml zu deklarieren, d.h. anwendungsweit. Dadurch wird nur eine Instanz erzeugt, die dann in allen Teilen der Anwendung genutzt wird.

    Um den Überblick zu behalten, sollte die Logik des Projektes in separate Geschäftsprozesse aufgeteilt werden. Zu jedem Geschäftsprozess gehört dann ein ViewModel und meist auch ein oder mehrere separate Datenpuffer. Jede View kann dann einen oder mehrere ViewModels nutzen bzw. unterschiedliche Views können den gleichen ViewModel (resp. Instanz) nutzen.

    Ich empfehle dir, erst einmal ein Konzept zu erarbeiten, wo welche Objekte genutzt werden sollen, indem möglicherweise die gesamte Lösung in separate Geschäftsprozesse aufgeteilt wird.


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Sonntag, 15. März 2020 08:27
  • Hi Peter,

    Vielen Dank für die ausführliche Antwort.

    Mit der globalen Ressource in App.xaml und mit Implementierung von "Source={StaticResource vm}" in allen Commands von allen Buttons und dem ContentControl im MainWindow funktioniert es nun endlich(;

    Kurze Fragen zum Abschluss des Threads:

    Wie kann dem DBContentUC der Wert einer bestimmenten Spalte in der Reihe des geklickten Buttons am besten übergeben werden?

    Grüße Tobias

    Sonntag, 15. März 2020 19:13
  • Hi Tobias,
    vermutlich hast du dir meine Beispiele nicht angeschaut. Ich hatte da als CommandParameter das Datenobjekt gebunden. In der Methode, die beim Klick aufgerufen wird, steht damit das konkrete Datenobjekt zur Verfügung und man hat alle Eigenschaften dieses Datenobjektes im Zugriff.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks


    Sonntag, 15. März 2020 19:26
  • Hallo Peter,

    doch das Beispiel habe ich mir angeschaut, allerdings soll bei mir der CommandParameter="ViewSQLContent" für den switch Case im Viewmodel übergeben werden und noch zusätzlich dazu der Inhalt von der jeweiligen Spalte.


    Sonntag, 15. März 2020 20:57
  • Hi Tobi,
    über einen Parameter beides übergeben geht nicht. Du musst also dein Konzept ändern. Eine Änderung könnte beispielsweise sein, eine andere ICommand-Eigenschaft nur für die Befehlsschaltflächen in den Spalten zu nutzen.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Montag, 16. März 2020 07:40
  • Hi Tobi,
    hier im thread habe ich dir am Donnerstag, 12. März 2020 08:51 ein passendes Beispiel gepostet. Welche Probleme hast du damit? Hast du es wenigstens mal auspribiert?

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Mittwoch, 18. März 2020 19:57