none
MVVM Treeview bind to command无效? RRS feed

  • 问题

  • 使用了Prism+Csla+AvalonDock

    View 代码如下:

     

    <ad:DockableContent x:Class="MES.Modules.Main.Navigation.NavigationListView"
              xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
              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:extToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit.Extended" 
              xmlns:infc="clr-namespace:MES.Infrastructure.Commands;assembly=MES.Infrastructure"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:my1="clr-namespace:Csla.Xaml;assembly=Csla.Xaml"
              mc:Ignorable="d" 
              Title="导航"
              d:DesignHeight="300" d:DesignWidth="300">
      <ad:DockableContent.Resources>
          
        <Style x:Key="LinkButton" TargetType="Button">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="Button">
                <ControlTemplate.Resources>
                  <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="TextDecorations" Value="Underline" />
                  </Style>
                </ControlTemplate.Resources>
                <ContentPresenter />
              </ControlTemplate>
            </Setter.Value>
          </Setter>
          <Setter Property="Foreground" Value="Blue" />
          <Setter Property="Cursor" Value="Hand" />
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
              <Setter Property="Foreground" Value="Red" />
            </Trigger>
          </Style.Triggers>
        </Style>
        
           
        <HierarchicalDataTemplate x:Key="NavigationTemplate" 
                     ItemsSource="{Binding Path=SubNavItemList}">
    
              <Button Content="{Binding Path=Name}"
                  Style="{StaticResource LinkButton}" 
                   Command="{Binding Path=DataContext.NavItemDoubleClickCommand,RelativeSource={RelativeSource FindAncestor, AncestorType=ad:DockableContent}}"
                   >
              </Button>
          
        </HierarchicalDataTemplate>
      </ad:DockableContent.Resources>
      
      <Grid x:Name="LayoutRoot">
    
        <TreeView ItemsSource="{Binding Model}" 
             ItemTemplate ="{StaticResource NavigationTemplate }" >
          
        </TreeView>
        <extToolkit:BusyIndicator IsBusy="{Binding Path=IsBusy}" BusyContent="正在加载菜单..." >
    
        </extToolkit:BusyIndicator>
    
      </Grid>
    </ad:DockableContent>
    

     

    view.cs 代码如下:

     

    using System.ComponentModel.Composition;
    using System.Windows.Controls;
    using System.Diagnostics.CodeAnalysis;
    using MES.Infrastructure;
    using AvalonDock;
    
    namespace MES.Modules.Main.Navigation
    {
      [ViewExport(RegionName = RegionNames.NavigationRegion, ViewName = "NavigationListView")]
      [PartCreationPolicy(CreationPolicy.NonShared)]
      public partial class NavigationListView : DockableContent
      {
        public NavigationListView()
        {
          InitializeComponent();
        }
    
        [Import]
        [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly", Justification = "Needs to be a property to be composed by MEF")]
        public NavItemListViewModel ViewModel
        {
          set
          {
            this.DataContext = value;
          }
    
          get
          {
            return (NavItemListViewModel)this.DataContext;
          }
        }
      }
    }
    

     

    ViewModel 代码如下:

    using System;
    using Csla.Xaml;
    using Csla;
    using System.ComponentModel.Composition;
    using Microsoft.Practices.Prism.Events;
    using System.Windows.Input;
    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.Prism.Regions;
    using Microsoft.Practices.ServiceLocation;
    using MES.Modules.Main.Models;
    using MES.Infrastructure;
    namespace MES.Modules.Main.Navigation
    {
      [Export(typeof(NavItemListViewModel))]
      [PartCreationPolicy(CreationPolicy.NonShared)]
      public class NavItemListViewModel:ViewModel<NavItemList>
      {
         #region Private members
    
        private readonly IRegionManager regionManager;
        private readonly IEventAggregator eventAggregator;
    
        #endregion
    
        #region Commandes
    
       
        public ICommand NavItemDoubleClickCommand { get; private set; }
           
    
        #endregion
    
    
        #region Constructor
        [ImportingConstructor]
        public NavItemListViewModel(IRegionManager regionManager, IEventAggregator eventAggregator)
        {
    
          this.InitializeCommands();
    
          this.regionManager = regionManager;
          this.eventAggregator = eventAggregator;
    
          InitData();
    
        }
    
        #endregion
    
        #region InitializeCommands Method
            
        public void InitializeCommands()
        {
          NavItemDoubleClickCommand = new DelegateCommand<object>(NavItemDoubleClick);
        }
    
        #endregion
    
        void InitData()
        {
          BeginRefresh("GetAll");
        }
    
    
        private void NavItemDoubleClick(object navItem)
        {
          /* if (menuItem is ProductCategory)
           {
             var productCategory = menuItem as ProductCategory;
             if (productCategory.ProductCategoryID > 0) // Category selected
               eventAggregator.Publish(new CategorySelectedEvent(productCategory));
             else // Category "all products" selected
               eventAggregator.Publish(new CategorySelectedEvent());
           }
           else if (menuItem is ProductSubcategory)
           {
             eventAggregator.Publish(new CategorySelectedEvent((ProductSubcategory)menuItem));
           }*/
          NavItem item = navItem as NavItem;
          // if (!string.IsNullOrEmpty(item.Name))
            // ShowView(item.ViewName);
        }
    
    
      }
    }
    
    

     

    当程序运行,可以获取TreeView.但是点击 Node不能触发NavItemdoubleClickCommand

    如果在View里直接用如下xaml可以触发该命令:

    <Grid x:Name="LayoutRoot">
    
    
        <Button Content="Test"
               Style="{StaticResource LinkButton}" 
                Command="{Binding Path=NavItemDoubleClickCommand}"
                >
        </Button>
       
    
      </Grid>
    

    如果以下方式,也不能触发该命令:

    <Grid x:Name="LayoutRoot">
    
    
        <Button Content="Test"
               Style="{StaticResource LinkButton}" 
                Command="{Binding Path=DataContext.NavItemDoubleClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=ad:DockableContent, AncestorLevel=1}}"
                >
        </Button>
       
    
      </Grid>
    

    这个问题困扰了我好久,请高人解答,谢谢

     

     

     

    2011年4月19日 16:41

答案

  •  

    我曾用如下代码进行了测试

    <Grid x:Name="LayoutRoot">
     <Button Content="Test" Cilck="Button_ClicK"
     Style="{StaticResource LinkButton}" 
     Command="{Binding Path=DataContext.NavItemDoubleClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=ad:DockableContent, AncestorLevel=1}}"
     >
     </Button>
     </Grid

    查看发现 datacontext 为 null

    目前,我改了View 部分,增加了collectionviewsoure 后可以行,以及一个Shell可以出发命令了,但是没弄明白是怎么回事。
    <ad:DockableContent x:Class="MES.Modules.Main.Navigation.NavigationListView"
         Name="this"
         xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
         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:extToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit.Extended" 
         xmlns:infc="clr-namespace:MES.Infrastructure.Commands;assembly=MES.Infrastructure"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:my1="clr-namespace:Csla.Xaml;assembly=Csla.Xaml"
         mc:Ignorable="d" 
         Title="导航"
         d:DesignHeight="300" d:DesignWidth="300">
     <ad:DockableContent.Resources>
       <CollectionViewSource x:Key="NavItemListViewModelViewSource"/> 
      <Style x:Key="LinkButton" TargetType="Button">
       <Setter Property="Template">
        <Setter.Value>
         <ControlTemplate TargetType="Button">
          <ControlTemplate.Resources>
           <Style TargetType="{x:Type TextBlock}">
            <Setter Property="TextDecorations" Value="Underline" />
           </Style>
          </ControlTemplate.Resources>
          <ContentPresenter />
         </ControlTemplate>
        </Setter.Value>
       </Setter>
       <Setter Property="Foreground" Value="Blue" />
       <Setter Property="Cursor" Value="Hand" />
       <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
         <Setter Property="Foreground" Value="Red" />
        </Trigger>
       </Style.Triggers>
      </Style>
      
        
      <HierarchicalDataTemplate x:Key="NavigationTemplate" 
             ItemsSource="{Binding Path=SubNavItemList}">
    
       <Button Content="{Binding Name}"
           Style="{StaticResource LinkButton}">
         
        <Button.InputBindings>
         <MouseBinding MouseAction="LeftDoubleClick"
           Command="{Binding Path=NavItemDoubleClickCommand,Source={StaticResource NavItemListViewModelViewSource}}"
            />
      
         </Button.InputBindings>
        </Button>
        
       
      </HierarchicalDataTemplate>
     </ad:DockableContent.Resources>
     
     <Grid x:Name="LayoutRoot">
    
      <TreeView ItemsSource="{Binding Model}" 
         ItemTemplate ="{StaticResource NavigationTemplate }" >
       
      </TreeView>
      <extToolkit:BusyIndicator IsBusy="{Binding Path=IsBusy}" BusyContent="正在加载菜单..." >
    
      </extToolkit:BusyIndicator>
    
     </Grid>
    </ad:DockableContent>
    
    

    using System.ComponentModel.Composition;
    using System.Windows.Controls;
    using System.Diagnostics.CodeAnalysis;
    using MES.Infrastructure;
    using System.Windows.Data;
    using AvalonDock;
    using System.Collections.ObjectModel;
    
    namespace MES.Modules.Main.Navigation
    {
     [ViewExport(RegionName = RegionNames.NavigationRegion, ViewName = "NavigationListView")]
     [PartCreationPolicy(CreationPolicy.NonShared)]
     public partial class NavigationListView : DockableContent
     {
      public NavigationListView()
      {
       InitializeComponent();
      }
    
      [Import]
      [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly", Justification = "Needs to be a property to be composed by MEF")]
      public NavItemListViewModel ViewModel
      {
       set
       {
        Shell.InitializeBindingResource(this, "NavItemListViewModelViewSource", value);
        
       }
    
       get
       {
        return (NavItemListViewModel)this.DataContext;
       }
      }
     }
    }
    
    

    增加了一个Shell class

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Controls;
    using Csla.Xaml;
    using System.Windows;
    using System.Collections.ObjectModel;
    namespace MES.Infrastructure
    {
     public static class Shell
     {
      public static void InitializeBindingResource(FrameworkElement form, string BindingResourceKey, object Model)
      {
    
       if (form != null && !string.IsNullOrEmpty(BindingResourceKey))
       {
        var resource = form.Resources[BindingResourceKey];
        if (resource == null)
         throw new NotSupportedException("Binding resource key not found in view resources");
    
        var viewsource = resource as System.Windows.Data.CollectionViewSource;
        if (viewsource != null)
        {
         // make sure model is a list (or wrapped in one)
         var list = Model as System.Collections.IEnumerable;
         if (list == null)
          list = new ObservableCollection<object>() { Model };
         viewsource.Source = list;
         form.DataContext = viewsource.Source;
        }
        else
        {
         var viewmodel = resource as Csla.Xaml.IViewModel;
         if (viewmodel != null)
          viewmodel.Model = Model;
         else
         {
          form.Resources.Remove(BindingResourceKey);
          form.Resources.Add(BindingResourceKey, Model);
         }
        }
       }
      }
     }
    }
    
    

    Model 部分的代码如下:

     

     

    using System.Text;
    using Csla;
    using Csla.Serialization;
    
    
    namespace MES.Modules.Main.Models
    {
     [Serializable ]
     public class NavItemList:ReadOnlyListBase <NavItemList ,NavItem >
     {
      #region Authorization Rules
    
      private static void AddObjectAuthorizationRules()
      {
       // TODO: add authorization rules
       //AuthorizationRules.AllowGet(typeof(ReadOnlyChildList), "Role");
      }
    
      #endregion
    
      #region Default Constructor
       private NavItemList() { }
      #endregion
    
      #region Asynchronous Factory Methods
      public static void New(EventHandler<DataPortalResult<NavItemList>> callback)
      {
       var dp = new DataPortal<NavItemList>();
       dp.CreateCompleted += callback;
       dp.BeginCreate();
      }
    
      public static void Get(int id, EventHandler<DataPortalResult<NavItemList>> callback)
      {
       var dp = new DataPortal<NavItemList>();
       dp.FetchCompleted += callback;
       // dp.BeginFetch(new NavMenu.Key(id));
      }
    
      public static void GetAll(EventHandler<DataPortalResult<NavItemList>> callback)
      {
       var dp = new DataPortal<NavItemList>();
       dp.FetchCompleted += callback;
       dp.BeginFetch();
      }
      #endregion // Asynchronous Factory Methods
    
      #region Data Access
    
      private void ReadData(IEnumerable<MES.Server.Entities.NavigationItem> data)
      {
         
       RaiseListChangedEvents = false;
       IsReadOnly = false;
    
       foreach (var item in data)
        this.Add(NavItem.Get(item));
       IsReadOnly = true;
       RaiseListChangedEvents = true;
    
      
      }	
    
    
    
      private void DataPortal_Fetch()
      {
       using (var ctx = Csla.Data.ObjectContextManager<MES.Server .Entities.SecurityEntityModelContainer>.GetManager(MES.Server.Entities.Database.Security ))
        ReadData(ctx.ObjectContext.NavigationItem.Where(p => p.ParentId == null));
      }
    
      private void Child_Fetch(int id)
      {
       using (var ctx = Csla.Data.ObjectContextManager<MES.Server.Entities.SecurityEntityModelContainer>.GetManager(MES.Server.Entities.Database.Security))
        ReadData(ctx.ObjectContext.NavigationItem.Where(p => p.ParentId == id));
      }
    
      #endregion
     }
    }
    

    using System;
    using Csla;
    using Csla.Data;
    
    namespace MES.Modules.Main.Models
    {
     [Serializable]
     public class NavItem : ReadOnlyBase<NavItem>
     {
      #region Business Methods
    
      public static readonly PropertyInfo<int> IdProperty = RegisterProperty<int>(c => c.Id);
      public int Id
      {
       get { return GetProperty(IdProperty); }
       private set { LoadProperty(IdProperty, value); }
      }
    
      public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(c => c.Name);
      public string Name
      {
       get { return GetProperty(NameProperty); }
       private set { LoadProperty(NameProperty, value); }
      }
      public static readonly PropertyInfo<NavItemList> SubNavItemListProperty = RegisterProperty<NavItemList>(c => c.SubNavItemList, RelationshipTypes.Child | RelationshipTypes.LazyLoad);
      public NavItemList SubNavItemList
      {
       get
       {
        if (!FieldManager.FieldExists(SubNavItemListProperty))
        {
         DataPortal.BeginFetch<NavItemListCreator>(Id,(o,e) =>
          {
           if (e.Error != null)
            throw e.Error;
           else 
            SubNavItemList =e.Object.Result;
    
          });
         return null;
        }
        return GetProperty(SubNavItemListProperty);
       }
       private set
       {
        LoadProperty(SubNavItemListProperty, value);
        OnPropertyChanged(SubNavItemListProperty);
       }
      }
      
      #endregion
    
    
      #region Default Constructor
    
      private NavItem() { }
    
      #endregion
    
      #region Synchronous Factory Methods
    
      internal static NavItem Get(MES.Server .Entities .NavigationItem data)
      {
       if (data == null)
        return null;
    
       return DataPortal.FetchChild<NavItem>(data);
      }
      #endregion 
    
    
      private void Child_Fetch(MES.Server .Entities .NavigationItem data)
      {
       LoadProperty(IdProperty, data.Id);
       // LoadProperty(ParentIdProperty, data.ParentId);
       LoadProperty(NameProperty, data.Name);
       // LoadProperty(TypeProperty, data.Type);
       // LoadProperty(ViewNameProperty, data.ViewName);
       // LoadProperty(BindingResourceKeyProperty, data.BindingResourceKey);
       // LoadProperty(ModelProperty, data.Model);
      }
    
     }
    }
    

     

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Csla;
    
    namespace MES.Modules.Main.Models
    {
     [Serializable]
     internal class NavItemListCreator : ReadOnlyBase<NavItemListCreator>
     {
      public static readonly PropertyInfo<NavItemList> ResultProperty = RegisterProperty<NavItemList>(c => c.Result);
      public NavItemList Result
      {
       get { return ReadProperty(ResultProperty); }
       private set { LoadProperty(ResultProperty, value); }
      }
    
      private void DataPortal_Fetch(int criteria)
      {
       // get data from database into repository objects or use L2S / EF ....
    
       Result = DataPortal.FetchChild<NavItemList>(criteria);
      }
    
     }
    }
    

     


    2011年4月21日 5:37

全部回复

  • 看上去应该没什么问题..

     

    如果在View里直接用如下xaml可以触发该命令:

     

    <Grid x:Name="LayoutRoot">
      <Button Content="Test"
          Style="{StaticResource LinkButton}" 
          Command="{Binding Path=NavItemDoubleClickCommand}"
          >
      </Button>
     </Grid>
    

     

    如果以下方式,也不能触发该命令:

     

    <Grid x:Name="LayoutRoot">
      <Button Content="Test"
          Style="{StaticResource LinkButton}" 
          Command="{Binding Path=DataContext.NavItemDoubleClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=ad:DockableContent, AncestorLevel=1}}"
          >
      </Button>
     </Grid>

    这个确实挺奇怪的..我觉得可以在起作用和不起作用时分别检查下DockableContent的DataContext是什么..


    just another day.
    2011年4月20日 14:39
  •  

    我曾用如下代码进行了测试

    <Grid x:Name="LayoutRoot">
     <Button Content="Test" Cilck="Button_ClicK"
     Style="{StaticResource LinkButton}" 
     Command="{Binding Path=DataContext.NavItemDoubleClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=ad:DockableContent, AncestorLevel=1}}"
     >
     </Button>
     </Grid

    查看发现 datacontext 为 null

    目前,我改了View 部分,增加了collectionviewsoure 后可以行,以及一个Shell可以出发命令了,但是没弄明白是怎么回事。
    <ad:DockableContent x:Class="MES.Modules.Main.Navigation.NavigationListView"
         Name="this"
         xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
         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:extToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit.Extended" 
         xmlns:infc="clr-namespace:MES.Infrastructure.Commands;assembly=MES.Infrastructure"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:my1="clr-namespace:Csla.Xaml;assembly=Csla.Xaml"
         mc:Ignorable="d" 
         Title="导航"
         d:DesignHeight="300" d:DesignWidth="300">
     <ad:DockableContent.Resources>
       <CollectionViewSource x:Key="NavItemListViewModelViewSource"/> 
      <Style x:Key="LinkButton" TargetType="Button">
       <Setter Property="Template">
        <Setter.Value>
         <ControlTemplate TargetType="Button">
          <ControlTemplate.Resources>
           <Style TargetType="{x:Type TextBlock}">
            <Setter Property="TextDecorations" Value="Underline" />
           </Style>
          </ControlTemplate.Resources>
          <ContentPresenter />
         </ControlTemplate>
        </Setter.Value>
       </Setter>
       <Setter Property="Foreground" Value="Blue" />
       <Setter Property="Cursor" Value="Hand" />
       <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
         <Setter Property="Foreground" Value="Red" />
        </Trigger>
       </Style.Triggers>
      </Style>
      
        
      <HierarchicalDataTemplate x:Key="NavigationTemplate" 
             ItemsSource="{Binding Path=SubNavItemList}">
    
       <Button Content="{Binding Name}"
           Style="{StaticResource LinkButton}">
         
        <Button.InputBindings>
         <MouseBinding MouseAction="LeftDoubleClick"
           Command="{Binding Path=NavItemDoubleClickCommand,Source={StaticResource NavItemListViewModelViewSource}}"
            />
      
         </Button.InputBindings>
        </Button>
        
       
      </HierarchicalDataTemplate>
     </ad:DockableContent.Resources>
     
     <Grid x:Name="LayoutRoot">
    
      <TreeView ItemsSource="{Binding Model}" 
         ItemTemplate ="{StaticResource NavigationTemplate }" >
       
      </TreeView>
      <extToolkit:BusyIndicator IsBusy="{Binding Path=IsBusy}" BusyContent="正在加载菜单..." >
    
      </extToolkit:BusyIndicator>
    
     </Grid>
    </ad:DockableContent>
    
    

    using System.ComponentModel.Composition;
    using System.Windows.Controls;
    using System.Diagnostics.CodeAnalysis;
    using MES.Infrastructure;
    using System.Windows.Data;
    using AvalonDock;
    using System.Collections.ObjectModel;
    
    namespace MES.Modules.Main.Navigation
    {
     [ViewExport(RegionName = RegionNames.NavigationRegion, ViewName = "NavigationListView")]
     [PartCreationPolicy(CreationPolicy.NonShared)]
     public partial class NavigationListView : DockableContent
     {
      public NavigationListView()
      {
       InitializeComponent();
      }
    
      [Import]
      [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly", Justification = "Needs to be a property to be composed by MEF")]
      public NavItemListViewModel ViewModel
      {
       set
       {
        Shell.InitializeBindingResource(this, "NavItemListViewModelViewSource", value);
        
       }
    
       get
       {
        return (NavItemListViewModel)this.DataContext;
       }
      }
     }
    }
    
    

    增加了一个Shell class

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Controls;
    using Csla.Xaml;
    using System.Windows;
    using System.Collections.ObjectModel;
    namespace MES.Infrastructure
    {
     public static class Shell
     {
      public static void InitializeBindingResource(FrameworkElement form, string BindingResourceKey, object Model)
      {
    
       if (form != null && !string.IsNullOrEmpty(BindingResourceKey))
       {
        var resource = form.Resources[BindingResourceKey];
        if (resource == null)
         throw new NotSupportedException("Binding resource key not found in view resources");
    
        var viewsource = resource as System.Windows.Data.CollectionViewSource;
        if (viewsource != null)
        {
         // make sure model is a list (or wrapped in one)
         var list = Model as System.Collections.IEnumerable;
         if (list == null)
          list = new ObservableCollection<object>() { Model };
         viewsource.Source = list;
         form.DataContext = viewsource.Source;
        }
        else
        {
         var viewmodel = resource as Csla.Xaml.IViewModel;
         if (viewmodel != null)
          viewmodel.Model = Model;
         else
         {
          form.Resources.Remove(BindingResourceKey);
          form.Resources.Add(BindingResourceKey, Model);
         }
        }
       }
      }
     }
    }
    
    

    Model 部分的代码如下:

     

     

    using System.Text;
    using Csla;
    using Csla.Serialization;
    
    
    namespace MES.Modules.Main.Models
    {
     [Serializable ]
     public class NavItemList:ReadOnlyListBase <NavItemList ,NavItem >
     {
      #region Authorization Rules
    
      private static void AddObjectAuthorizationRules()
      {
       // TODO: add authorization rules
       //AuthorizationRules.AllowGet(typeof(ReadOnlyChildList), "Role");
      }
    
      #endregion
    
      #region Default Constructor
       private NavItemList() { }
      #endregion
    
      #region Asynchronous Factory Methods
      public static void New(EventHandler<DataPortalResult<NavItemList>> callback)
      {
       var dp = new DataPortal<NavItemList>();
       dp.CreateCompleted += callback;
       dp.BeginCreate();
      }
    
      public static void Get(int id, EventHandler<DataPortalResult<NavItemList>> callback)
      {
       var dp = new DataPortal<NavItemList>();
       dp.FetchCompleted += callback;
       // dp.BeginFetch(new NavMenu.Key(id));
      }
    
      public static void GetAll(EventHandler<DataPortalResult<NavItemList>> callback)
      {
       var dp = new DataPortal<NavItemList>();
       dp.FetchCompleted += callback;
       dp.BeginFetch();
      }
      #endregion // Asynchronous Factory Methods
    
      #region Data Access
    
      private void ReadData(IEnumerable<MES.Server.Entities.NavigationItem> data)
      {
         
       RaiseListChangedEvents = false;
       IsReadOnly = false;
    
       foreach (var item in data)
        this.Add(NavItem.Get(item));
       IsReadOnly = true;
       RaiseListChangedEvents = true;
    
      
      }	
    
    
    
      private void DataPortal_Fetch()
      {
       using (var ctx = Csla.Data.ObjectContextManager<MES.Server .Entities.SecurityEntityModelContainer>.GetManager(MES.Server.Entities.Database.Security ))
        ReadData(ctx.ObjectContext.NavigationItem.Where(p => p.ParentId == null));
      }
    
      private void Child_Fetch(int id)
      {
       using (var ctx = Csla.Data.ObjectContextManager<MES.Server.Entities.SecurityEntityModelContainer>.GetManager(MES.Server.Entities.Database.Security))
        ReadData(ctx.ObjectContext.NavigationItem.Where(p => p.ParentId == id));
      }
    
      #endregion
     }
    }
    

    using System;
    using Csla;
    using Csla.Data;
    
    namespace MES.Modules.Main.Models
    {
     [Serializable]
     public class NavItem : ReadOnlyBase<NavItem>
     {
      #region Business Methods
    
      public static readonly PropertyInfo<int> IdProperty = RegisterProperty<int>(c => c.Id);
      public int Id
      {
       get { return GetProperty(IdProperty); }
       private set { LoadProperty(IdProperty, value); }
      }
    
      public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(c => c.Name);
      public string Name
      {
       get { return GetProperty(NameProperty); }
       private set { LoadProperty(NameProperty, value); }
      }
      public static readonly PropertyInfo<NavItemList> SubNavItemListProperty = RegisterProperty<NavItemList>(c => c.SubNavItemList, RelationshipTypes.Child | RelationshipTypes.LazyLoad);
      public NavItemList SubNavItemList
      {
       get
       {
        if (!FieldManager.FieldExists(SubNavItemListProperty))
        {
         DataPortal.BeginFetch<NavItemListCreator>(Id,(o,e) =>
          {
           if (e.Error != null)
            throw e.Error;
           else 
            SubNavItemList =e.Object.Result;
    
          });
         return null;
        }
        return GetProperty(SubNavItemListProperty);
       }
       private set
       {
        LoadProperty(SubNavItemListProperty, value);
        OnPropertyChanged(SubNavItemListProperty);
       }
      }
      
      #endregion
    
    
      #region Default Constructor
    
      private NavItem() { }
    
      #endregion
    
      #region Synchronous Factory Methods
    
      internal static NavItem Get(MES.Server .Entities .NavigationItem data)
      {
       if (data == null)
        return null;
    
       return DataPortal.FetchChild<NavItem>(data);
      }
      #endregion 
    
    
      private void Child_Fetch(MES.Server .Entities .NavigationItem data)
      {
       LoadProperty(IdProperty, data.Id);
       // LoadProperty(ParentIdProperty, data.ParentId);
       LoadProperty(NameProperty, data.Name);
       // LoadProperty(TypeProperty, data.Type);
       // LoadProperty(ViewNameProperty, data.ViewName);
       // LoadProperty(BindingResourceKeyProperty, data.BindingResourceKey);
       // LoadProperty(ModelProperty, data.Model);
      }
    
     }
    }
    

     

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Csla;
    
    namespace MES.Modules.Main.Models
    {
     [Serializable]
     internal class NavItemListCreator : ReadOnlyBase<NavItemListCreator>
     {
      public static readonly PropertyInfo<NavItemList> ResultProperty = RegisterProperty<NavItemList>(c => c.Result);
      public NavItemList Result
      {
       get { return ReadProperty(ResultProperty); }
       private set { LoadProperty(ResultProperty, value); }
      }
    
      private void DataPortal_Fetch(int criteria)
      {
       // get data from database into repository objects or use L2S / EF ....
    
       Result = DataPortal.FetchChild<NavItemList>(criteria);
      }
    
     }
    }
    

     


    2011年4月21日 5:37
  • OK, 代码很多,而且看上去有点复杂.其实你的问题可以先简化下,主要是由于那个Command邦定没有找到DataContext造成的。所以我们的焦点可以放在你的 View 什么时候设置了他自己的DataContext也就是什么时候设置了他的 ViewModel 属性。所以你应该跟踪下,看下调用这个DockableContent 的地方,在什么时候调用并且设置 ViewModel 属性。

    我简化了你的设计,做了个简单的模型,在调用我自己的UserControl的地方,设置了VM属性,这个小模型也许对你有用:http://cid-51b2fdd068799d15.office.live.com/self.aspx/.Public/TestCase/20110422%5E_CommandInMVVM%5E_TestCase.zip

    Sincerely,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年4月22日 8:56
    版主