Click here to Skip to main content
15,125,968 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
Hi Friends

I have 2 different user controls i.e.
ViewAUserControl.xaml
, and
ViewBUserControl.xaml
.

These controls are added dynamically in dynamic tabItems where each tabItem contains any single userControl from availabe 2 UserControls, whom names are mentioned above.

Problem is that I want to implement logic in ViewModel for each user control i.e for Button Click but when I mention DataContext in UserControl then StackOverFlow Exception Occurs.

What I have tried:

here is my <pre>ViewAUserControl.xaml

<UserControl x:Class="WpfPractice.View.ViewAUserControl"
             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:WpfPractice.View"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <!--<UserControl.DataContext>
        <local:ViewAUserControl></local:ViewAUserControl>
    </UserControl.DataContext>-->
    <Grid>
        <Button Command="{Binding btnCmd}" Content="A" Height="30" Width="100"></Button>
    </Grid>
</UserControl>



here is my
ViewBUserControl.xaml

<UserControl x:Class="WpfPractice.View.ViewBUserControl"
             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:WpfPractice.View"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <!--<UserControl.DataContext>
        <local:ViewBUserControl></local:ViewBUserControl>
    </UserControl.DataContext>-->
    <Grid>
        <Button Command="{Binding btnCmd}" Content="B" Height="30" Width="100"></Button>
    </Grid>
</UserControl>



here is Main Tab Window TabWindow.xaml
HTML
<Window x:Class="WpfPractice.View.TabWindow"
        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:my="clr-namespace:WpfPractice.View"
        xmlns:vm="clr-namespace:WpfPractice.ViewModel"
        mc:Ignorable="d"
        Title="TabWindow" Height="300" Width="300">
    <Grid>
        <Grid.Resources>
            <vm:TabViewModel x:Key="TabVM"></vm:TabViewModel>
        </Grid.Resources>
        <TabControl x:Name="MyTabControl"
            ItemsSource="{Binding TabViewModels}" DataContext="{StaticResource TabVM}"
           SelectedItem="{Binding SelectedTabViewModel}" >

            <TabControl.Resources>
                <DataTemplate DataType="{x:Type vm:ViewModelA}">
                    <my:ViewAUserControl />
                </DataTemplate>
                <DataTemplate DataType="{x:Type vm:ViewModelB}">
                    <my:ViewBUserControl />
                </DataTemplate>
            </TabControl.Resources>

            <TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Setter Property="Header" Value="{Binding Header}" />
                </Style>
            </TabControl.ItemContainerStyle>

        </TabControl>
    </Grid>
</Window>






An Interface for each Controls's View Model
ITabViewModel.cs

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfPractice.Model
{
    public interface ITabViewModel
    {
        String Header { get; set; }
    }
}


Main Tab's View Model TabViewModel.cs
C#
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfPractice.Model;

namespace WpfPractice.ViewModel
{
    public class TabViewModel
    {
        public ObservableCollection<ITabViewModel> TabViewModels { get; set; }

        public TabViewModel()
        {
            TabViewModels = new ObservableCollection<ITabViewModel> ();
            TabViewModels.Add(new ViewModelA { Header = "Tab A" });
            TabViewModels.Add(new ViewModelB { Header = "Tab B" });
            TabViewModels.Add(new ViewModelA { Header = "Tab D" });
            TabViewModels.Add(new ViewModelB { Header = "Tab E" });
        }
    }
}



View model for UserControlA ViewModelA.cs
C#
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfPractice.Model;

namespace WpfPractice.ViewModel
{
    public class ViewModelA : BindableBase, ITabViewModel
    {
        int count = 0;
        DelegateCommand btnCmd; //=new DelegateCommand()
        string header;
        public string Header { get=>header; set=>SetProperty(ref header, value); }
        public ViewModelA()
        {
            btnCmd = new DelegateCommand(Execute);
        }
        bool canExecute()
        {
            return true;
        }
        void Execute()
        {
            Header = Header + (count++.ToString());
        }
    }
}



View model for UserControlB ViewModelB.cs
C#
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfPractice.Model;

namespace WpfPractice.ViewModel
{
    public class ViewModelB : BindableBase, ITabViewModel
    {
        int count = 0;
        DelegateCommand btnCmd; //=new DelegateCommand()
        string header;
        public string Header { get=>header; set=>SetProperty(ref header, value); }
        public ViewModelB()
        {
            btnCmd = new DelegateCommand(Execute);
        }
        bool canExecute()
        {
            return true;
        }
        void Execute()
        {
            Header = Header + (count++.ToString());
        }
    }
}



Problem: I want to implement logic in ViewModel for each user control i.e for Button Click but when I mention DataContext in UserControl then StackOverFlow Exception Occurs. Kindly guide me to where bind DelegateCommand or ICommand ????
Posted
Updated 9-Nov-21 9:46am
v3
Comments
Gerry Schmitz 29-Jul-20 14:09pm
   
The consequences of "thou shalt not code-behind". But HTML and JavaScript (inline!) are avant-garde.

1 solution

In the ViewAUserControl.xaml:
xmlns:local="clr-namespace:WpfPractice.ViewModel"
<UserControl.DataContext>
   <local:ViewModelA></local:ViewModelA>
</UserControl.DataContext>

In the ViewBUserControl.xaml:
xmlns:local="clr-namespace:WpfPractice.ViewModel"
<UserControl.DataContext>
  <local:ViewModelB></local:ViewModelB>
</UserControl.DataContext>
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900