TabControl - 共享主ViewModel

时间:2014-10-23 08:41:16

标签: c# wpf mvvm

我希望能够在主窗口和标签控件之间共享控件。现在,我在主窗口上有一个选项卡控件和状态栏。状态栏包含一个按钮和进度条。我想分享进度条。单击该按钮时,它会重置进度条。

标签包含一个按钮。单击时,它应将进度条增加1。

我做了什么:在整天挖掘SO /其他之后,我能够做到这一点。

  • MainWindowView
  • - >在xaml
  • 中声明MainWindowViewModel的实例
  • - >声明制表符作为xaml b / c中的usercontrols将始终具有相同的制表符
  • TabControl1View
  • - >在xaml
  • 中声明TabControl2ViewModel的实例

我需要有关如何与TabControl1View中的MainWindowViewModel对话的建议。

<Window x:Class="TabControlTest.MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TabControlTest"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<DockPanel>
    <StatusBar DockPanel.Dock="Bottom">
        <StatusBarItem HorizontalContentAlignment="Stretch" DockPanel.Dock="Top">
            <Button Height="25" Content="Reset" Command="{Binding MainWindowViewModel_ButtonClickCommand}"/>
        </StatusBarItem>
        <StatusBarItem HorizontalContentAlignment="Stretch" DockPanel.Dock="Bottom">
            <ProgressBar Height="25" Maximum="10" Value="{Binding MainWindowViewModel_Progress, Mode=TwoWay}"/>
        </StatusBarItem>
    </StatusBar>
    <TabControl>
        <TabItem>
            <local:TabControl1View/>
        </TabItem>
    </TabControl>
</DockPanel>

class MainWindowViewModel : ViewModelBase
{
    int progress = 0;

    public int MainWindowViewModel_Progress
    {
        get
        {
            return progress;
        }
        set
        {
            SetAndNotify(ref this.progress, value, () => this.MainWindowViewModel_Progress);
        }
    }

    ICommand _ButtonClickCommand;

    public ICommand MainWindowViewModel_ButtonClickCommand
    {
        get
        {
            return _ButtonClickCommand ?? (_ButtonClickCommand = new CommandHandler(() => MainWindowViewModel_ButtonClick(), true));
        }
    }

    public void MainWindowViewModel_ButtonClick()
    {
        MainWindowViewModel_Progress = 0; // Reset progress
    }
}

X

<UserControl x:Class="TabControlTest.TabControl1View"
         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:TabControlTest"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
    <local:TabControl1ViewModel/>
</UserControl.DataContext>
<Grid>
    <Button Content="UP" Command="{Binding TabControl1ViewModel_UpClickCommand}"/>
</Grid>

class TabControl1ViewModel : ViewModelBase
{
    ICommand _UpClickCommand;

    public ICommand TabControl1ViewModel_UpClickCommand
    {
        get
        {
            return _UpClickCommand ?? (_UpClickCommand = new CommandHandler(() => TabControl1ViewModel_UpClick(), true));
        }
    }

    public void TabControl1ViewModel_UpClick()
    {
        // I want to increase the progress bar here
    }
}

我在这里找到了一个使用中介模式的好答案: How can I update a property of mainWindowViewModel from another ViewModel?

但我不明白如何在MainWindowViewModel中存储对TabControl1ViewModel的引用。

还发现大量文章说要在MainViewModel中声明ViewModel并跟踪它们,但它们总是代码片段。

问题:如何将MainViewModel.Progress传递给TabControlViewModel?

我现在正试图在我的MainViewModel中添加类似的东西

MainViewModel.ProgressChanged = TabControlView。(获取TabControlViewModel).ProgressChanged

1 个答案:

答案 0 :(得分:1)

当你这样做时

<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>

<UserControl.DataContext>
    <local:TabControl1ViewModel/>
</UserControl.DataContext>

您要让View自行创建MainWindowViewModelTabControl1ViewModel的实例,并将其绑定到View的datacontext。这使您无法控制将任何构造函数参数传递给控件。

MainWindowViewModel的构造函数中初始化用户控件的Datacontext,如

class MainWindowViewModel
{
    MainWindowViewModel
    {
     ChildViewModel  = new TabControl1ViewModel(this);
    }
    public TabControl1ViewModel ChildViewModel {get; private set;}
}

class TabControl1ViewModel
{
    public MainWindowViewModel ParentViewModel {get; private set;}
    TabControl1ViewModel(MainWindowViewModel mainWindowViewModel)
    {
        ParentViewModel  = mainWindowViewModel;
    }
}

View.Xaml

<Window x:Class="TabControlTest.MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TabControlTest"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<DockPanel>
  .
  .
  .
   <TabControl>
        <TabItem>
            <local:TabControl1View DataContext={Binding ChildViewModel}/>
        </TabItem>
   </TabControl>
</DockPanel>