用户控件和窗口中的WPF多个ViewModel实例

时间:2018-01-21 13:39:20

标签: wpf

这是我关于stackoverflow的第一个问题。 我有一个Usercontrol包含一个viewModel作为静态资源。比我有一个包含这个UserModel的窗口。我想将命令从Window发送到usercontrol使用的viewmodel。所以我将Viewmodel类绑定到Usercontrol,并将Window作为静态资源绑定到Window。但是viewmodell是2次实例化的。一旦从Window和一次从usercontrol。我究竟做错了什么?

这是usercontrol的xaml:

<UserControl x:Class="ScanVM.ScanView"
         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:t="clr-namespace:ScanVM"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="501.305">
<UserControl.Resources>
    <t:ScanVM x:Key="ABC"/>
</UserControl.Resources>
<DockPanel DataContext="{Binding Source={StaticResource ABC}}">
    <Grid ShowGridLines="True" Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="5*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="10*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <Label Content="Geräte:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" Margin="0,10,10,0"/>
        <DataGrid ItemsSource="{Binding Path=ScanIDs, Mode=OneWay}" Grid.Column="1" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" AutoGenerateColumns="false" Height="152" >
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding ScanIds}" ClipboardContentBinding="{x:Null}" Header="Bezeichnung" MinWidth="200"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</DockPanel>

这是我窗口的代码:

<Window x:Class="ScanViewer.MainWindow"
    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:ribbon="clr-namespace:System.Windows.Controls.Ribbon;assembly=System.Windows.Controls.Ribbon"
    xmlns:self="clr-namespace:ScanViewer"
    xmlns:t="clr-namespace:ScanVM;assembly=ScanVM"
    mc:Ignorable="d"
    Title="Scan-Viewer" Height="682.225" Width="694">
<Window.Resources>
    <t:ScanVM x:Key="ABC"/>
</Window.Resources>
<Window.CommandBindings>  
    <CommandBinding
        Command="self:MainWindow.ExitCommand"
        CanExecute="ExitCommand_CanExecute"
        Executed="ExitCommand_Execute"/> 
</Window.CommandBindings>
<DockPanel>
    <ribbon:Ribbon DockPanel.Dock="Top">
        <Ribbon.ApplicationMenu>
            <RibbonApplicationMenu Visibility="Collapsed"> 
                <RibbonApplicationMenuItem Header="Beenden"/>
                <RibbonApplicationMenu.FooterPaneContent>
                    <RibbonButton Label="Exit"/>
                </RibbonApplicationMenu.FooterPaneContent>
            </RibbonApplicationMenu>
        </Ribbon.ApplicationMenu>
        <RibbonTab Header="Start">
            <RibbonGroup Header="Programm">
                <RibbonButton Label="Beenden" Margin="0,5,0,0" Command="self:MainWindow.ExitCommand" />  
            </RibbonGroup>
            <RibbonGroup Header="Scannen">
                <RibbonButton Label="Daten Scannen" Margin="0,5,0,0" Command="{Binding ScanCmd, Source={StaticResource ABC}}"/>
            </RibbonGroup>
        </RibbonTab>
    </ribbon:Ribbon>
    <Grid DockPanel.Dock="Top" Height="464">
        <t:ScanView DataContext="{Binding Source={StaticResource ABC}}"/>
    </Grid>
</DockPanel>

这是我的Viewmodel的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Windows.Input;
using System.Threading;
using MVVMBase;

namespace ScanVM
{
   public class ScanVM : ViewModelBase
   {
      private ICommand _doWorkCmd;
      private ICommand _scanCmd;

      private bool scanAllowed = false;

      public List<int> ScanIDs
      {
         get;
         set;
      }

      public ScanVM()
      {
         _doWorkCmd = new DelegateCommand((param) => DoWork());
         _scanCmd = new DelegateCommand((param) => Scan());
      }

      public bool NWScanAllowed(object executeAllowed)
      {
         return scanAllowed;
      }


      public ICommand WorkCmd
      {
         get { return _doWorkCmd; }
      }

      public ICommand ScanCmd
      {
         get
         {
            return _scanCmd;
         }
      }

      private void Scan()
      {
            scanAllowed = true;
      }

      private void DoWork()
      {

      }
   }
}

1 个答案:

答案 0 :(得分:0)

答案取决于您要对共享对象执行的操作。

您可以将ABC移至<Application.Resources>标记内的App.xaml,以便在整个项目中共享它。

或者您可以删除用户控件中的那个并在窗口的资源中使用ABC。

在这种情况下,您需要一个有效的参考路径来处理来自用户控件的 窗口资源中的ABC

将我们带到这两种情况:

  1. 可以找到有效路径:
  2. 因此,如果您的用户控件是所提到窗口的一部分(并且,如果窗口的DataContext设置为ABC),那么请在用户控件内部进行说明像这样引用它:

    <DockPanel DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext}">
    
    1. 无法找到有效路径and you just want the static resource。如果你坚持这样做,最好将资源移到App.xaml,而不是尝试调整它。