0

My application

I divided the main window in 3 parts, the left and the right part allow the user to either select private message or public channel which get displayed on the middle panel. My problem is that the buttons on the sides that allow to display the correct UserControl are a child of a child of a child and I don't know how to modify the ContentControl of the MainWindow from this many children.

Inside of my MainWindow I have a ContentControl that display the correct Control (ChatViewModel is a UserControl, I am just to lazy to rename it)

<ContentControl Grid.Row="1" Grid.Column="1" DataContext="{Binding Selection}" x:Name="MainPanel">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type chat:UserMessages}">
                <chat:ChatViewModel DataContext="{Binding Selection}"/>
            </DataTemplate>

            <DataTemplate DataType="{x:Type channel:ChannelClass}">
                <channel:PrintChannel DataContext="{Binding Selection}"/>
            </DataTemplate>
        </ContentControl.Resources>
    </ContentControl>

Selection is a variable that I declare in the C# code of the MainWindow. I looked at dependency properties and other stuff but I can't make anything work. Even if the answer is not pretty, I need this to work!

Dharman
  • 30,962
  • 25
  • 85
  • 135
Dave
  • 11
  • 4
  • We don't really value lazyness, I think. Rename the thing and make it easier for us to help you. – Thomas Weller Jun 20 '21 at 11:01
  • If I understand correctly, then you need to create a button in the child elements for which the click will be processed at higher levels (including the Window level). For WPF, one of the typical, commonly used solutions to these problems is to use the RoutedCommand. At the button level, only set the Command and CommanParameter. And the processing is carried out at any level higher in the visual tree. – EldHasp Jun 20 '21 at 11:10
  • I think the name is better now, but I don't see how I can make it easier for people to help me apart from showing a lot of code which would make my post unreadable. As I said I already searched for the answer but couldn't make anything work. – Dave Jun 20 '21 at 11:10
  • @EldHasp this might be exatcly what I am looking for, do you have any example? If not I can go look on google my best friend. – Dave Jun 20 '21 at 11:12

1 Answers1

0

A simple example without small details.
I think you can easily understand it.
If you need to clarify something - write.

using Simplified;
using System.Windows;

namespace BindingRoutedCommand
{
    public class MainViewModel
    {
        private RelayCommand _exampleCommand;

        public RelayCommand ExampleCommand => _exampleCommand
            ?? (_exampleCommand = new RelayCommand(p => MessageBox.Show($"Hi {p}!")));
    }
}
using System.Windows.Input;

namespace BindingRoutedCommand
{
    public static class MyRoutedCommands
    {
        public static RoutedUICommand Hello { get; } = new RoutedUICommand(nameof(Hello), nameof(Hello), typeof(MyRoutedCommands));
    }
}
<UserControl x:Class="BindingRoutedCommand.ExampleUC"
             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:BindingRoutedCommand"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button Content="Say hello" Padding="15 5"
                Command="{x:Static local:MyRoutedCommands.Hello}"
                CommandParameter="Dave"/>
    </Grid>
</UserControl>
<Window x:Class="BindingRoutedCommand.ExampleWindow"
        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:BindingRoutedCommand"
        mc:Ignorable="d"
        Title="ExampleWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static local:MyRoutedCommands.Hello}"
                        Executed="OnExecutedHello"/>
    </Window.CommandBindings>
    <Grid>
        <local:ExampleUC VerticalAlignment="Center" HorizontalAlignment="Center" />
    </Grid>
</Window>
using Simplified;
using System.Windows;

namespace BindingRoutedCommand
{
    public partial class ExampleWindow : Window
    {
        public ExampleWindow()
        {
            InitializeComponent();
        }

        private void OnExecutedHello(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            MainViewModel viewModel = (MainViewModel)DataContext;
            viewModel.ExampleCommand.TryExecute(e.Parameter);
        }
    }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
EldHasp
  • 6,079
  • 2
  • 9
  • 24
  • First thanks a lot for your answer!! If i understand correctly, the function that I need to modify to do what I want is the ExampleCommand ? And with your code, I have an Error "Delegate 'Action' doesn't accept argument 1" on the argument of the new RelayCommand. – Dave Jun 20 '21 at 12:19
  • It depends on the implementation of RelayCommand and TryExecute. Usage example with implementations from answers: https://stackoverflow.com/questions/67597202/how-to-fix-this-behavior-in-a-wpf-tabcontrol/67617794#67617794 and https://stackoverflow.com/questions/67763024/display-deleted-rows-in-a-datatable/67770545#67770545 – EldHasp Jun 20 '21 at 12:41
  • In the example, the ExampleCommand is initialized with a lambda. But you can also pass a method there. The method must be without a parameter or with one parameter. If the type of the method parameter is different from object, then `RelayComman` should be used. – EldHasp Jun 20 '21 at 12:44
  • I think I figured it out but I have one last question, before I used to defines 3 variables in the MainWindow.cs and set the DataContext to these 3 variables. Now with your solution I set the DataContext to the MainViewModel, how do I pass the same 3 variables in the DataContext? Do i just move them inside? – Dave Jun 20 '21 at 13:13
  • I don't understand what you mean by variables and their passing. You have too few details in the question. Can you add more details related to the issues under discussion there? – EldHasp Jun 20 '21 at 13:47
  • If by discussion you mean here in the comments, well I have 3 variables `UserMessages`, `UserFriends` and `PublicMain`. Before your solution I had setted the DataContext as `new {UserMessages,UserFriends,PublicMain}` but now I set the DataContext to `DataContext = new MainViewModel`. What should I do with my variables to still have access to them from my MainWindow.xaml? If its not clear I can create a new post with my related code. – Dave Jun 20 '21 at 13:58
  • I do not understand your explanations. I need at least a bit of demo code related to your explanation. Create a new topic or add in the same topic to your question - decide for yourself. – EldHasp Jun 20 '21 at 14:13