Click here to Skip to main content
15,885,141 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 8:46am
v3
Comments
[no name] 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>
 
Share this answer
 

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