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 (встроенные!)-это авангард.