我用UserControls處理這個問題的方式是我的shell視圖模型將同時引用ToolbarViewModel和DataEntryViewModel。工具欄將爲每個可能的命令觸發一個事件,並且shell視圖模型將適當地處理事件。下面是一個示例:
在MainView中,爲每個可能的DataEntry視圖/視圖模型創建一個DataTemplate。然後將ContentPresenter綁定到DataEntryViewModel的基本類型的MainViewModel中的屬性。
<Window
//usual window declarations>
<Window.Resources>
<DataTemplate DataType="{x:Type vm:DataEntryViewModel}">
<view:DataEntryView />
</DataTemplate>
//more DataTemplates for other data entry views
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<view:ToolbarView Grid.Row="0"
DataContext="{Binding ToolbarContext}" />
<ContentPresenter Grid.Row="1"
Content="{Binding DataEntryContext}" />
</Grid>
</Window>
DataEntryViewModel將爲工具欄可能要執行的所有不同的可能操作提供一種方法。爲了簡潔起見,我只提供了Save方法。
public interface IDataEntryViewModelBase
{
void Save();
}
public abstract class DataEntryViewModelBase : ViewModelBase, IDataEntryViewModelBase
{
public virtual void Save()
{
//base save work
}
}
public class DataEntryViewModel : DataEntryViewModelBase
{
public override void Save()
{
base.Save();
//unique save work
}
}
ToolbarViewModel爲每個可執行的命令都有一個事件。
public class ToolbarViewModel : ViewModelBase, IToolbarViewModel
{
//can just use EventArgs here if no need to pass data when this event fires
public event EventHandler<SaveExecutedArgs> SaveExecuted;
public ICommand CmdSave
{
get { return new RelayCommand(() => OnSaveExecuted()); }
}
protected void OnSaveExecuted()
{
var handler = SaveExecuted;
if (handler == null) return;
handler(this, new SaveExecutedArgs());
}
}
MainViewModel具有工具欄DataContext的屬性和DataEntry DataContext的屬性。當分配ToolbarContext時,我爲工具欄公開的每個命令事件註冊一個方法。在事件處理程序中,我爲該事件調用DataEntryContext的適當方法。
public class MainViewModel : ViewModelBase
{
private IToolbarViewModel _toolbarContext;
public IToolbarViewModel ToolbarContext
{
get { return _toolbarContext; }
set { Set("ToolbarContext", ref _toolbarContext, value); }
}
private IDataEntryViewModelBase _dataEntryContext;
public IDataEntryViewModelBase DataEntryContext
{
get { return _dataEntryContext; }
set { Set("DataEntryContext", ref _dataEntryContext, value); }
}
public MainViewModel()
{
_toolbarContext = new ToolbarViewModel();
_toolbarContext.SaveExecuted += ToolbarContext_SaveExecuted;
_dataEntryContext = new DataEntryViewModel();
}
private void ToolbarContext_SaveExecuted(object sender, SaveExecutedArgs e)
{
//can change this to popup a warning or however you want to handle it
//under the circumstance that DataEntryContext is null
if (DataEntryContext == null) return;
DataEntryContext.Save();
}
}
您是否在使用棱鏡?通常,我在我的viewmodel中實現IActiveAware,區域管理器自動在我的ViewModel和View上設置IsActive。然後我創建一個「SaveCommand」這是一個CompositeCommand並註冊每個ViewModel的命令。當ViewModel處於活動狀態時,切換其命令的IsActive屬性,因此只調用正確的屬性。 – Alan
是的,我正在使用棱鏡。雖然我對棱鏡和WPF是新手,但是我的知識是有限的。我一定會檢查出來。 –