DoingWork Ответов: 0

WPF с использованием MVVM: как привязать кнопку в UserControl в динамических tabitems


Привет Друзья

У меня есть 2 различных пользовательских элемента управления, т. е.
ViewAUserControl.xaml
, и
ViewBUserControl.xaml
.

Эти элементы управления добавляются динамически в динамические tabItems, где каждый tabItem содержит любой отдельный userControl из availabe 2 UserControls, имена которых упомянуты выше.

Проблема в том, что я хочу реализовать логику в ViewModel для каждого пользовательского элемента управления, то есть для нажатия кнопки, но когда я упоминаю DataContext в UserControl, то возникает исключение StackOverFlow.

Что я уже пробовал:

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>



вот мой
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>



вот главное окно вкладки TabWindow.xaml
<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>






Интерфейс для модели представления каждого элемента управления
ITabViewModel.cs

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; }
    }
}


Модель представления главной вкладки TabViewModel.cs
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" });
        }
    }
}



Модель представления для UserControlA ViewModelA.cs
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());
        }
    }
}



Модель представления для UserControlB ViewModelB.cs
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());
        }
    }
}



Проблема: я хочу реализовать логику в ViewModel для каждого пользовательского элемента управления, то есть для нажатия кнопки, но когда я упоминаю DataContext в UserControl, то возникает исключение StackOverFlow. Пожалуйста, направьте меня туда, где привязать DelegateCommand или ICommand ????

Gerry Schmitz

Последствия "ты не должен скрываться за кодом". Но HTML и JavaScript (встроенные!)-это авангард.

0 Ответов