我遇到了問題,從我的viewmodel引發的事件有時在視圖中將datacontext顯示爲null。我開始認爲這是一個弱綁定模式問題,並且我沒有使用它,或者誤解它(對於設計模式來說是新的,並且幾個月前啓動了WPF)。在事件期間間歇性地使用DataContext
相關MainWindow.xaml
<Grid Tree:TreeView.ItemSelected="DisplayRequested"
Tree:TreeView.PoolCategoriesChanged="PoolContentChanged">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="0" VerticalAlignment="Stretch"/>
<GridSplitter Grid.Column="1" VerticalAlignment="Stretch"
Background="Gray" ShowsPreview="True" Width="5"
HorizontalAlignment="Center"/>
<GridSplitter Grid.Column="2" VerticalAlignment="Stretch"/>
<Tree:TreeView Name="poolTree" Grid.Column="0" Focusable="True" />
<ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto">
<Details:DetailsView Name="detailsDisplay" Focusable="True"/>
</ScrollViewer>
</Grid>
相關的代碼背後
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var vm = (CLUViewModel)e.NewValue;
if (vm == null) return;
vm.OwnerCleanupStarted += OnOwnerCleanupStarting;
vm.OwnerCleanupEnded += OnOwnerCleanupEnding;
}
#region Event Handlers
private void OnOwnerCleanupEnding(object sender, EventArgs e)
{
ViewServices.CloseProgressDialog();
}
private void OnOwnerCleanupStarting(object sender, EventArgs e)
{
var vm = DataContext as CLUViewModel;
if (vm == null) return;
var progressDialogViewModel = vm.ProgressDialogVM;
ViewServices.ShowProgressDialog(GetWindow(this), progressDialogViewModel);
}
#endregion
}
我有幾個RoutedEvents
似乎沒有問題的功能。儘管如此,OnOwnerCleanupStarting
事件似乎在var vm = DataContext as CLUViewModel;
上返回null。這是因爲它太強烈,而且沒有使用WPF框架?
如果我把它放在調試和跟蹤通過它總是工作,並且在正常使用過程中多次工作沒有錯誤。這是一種競爭條件,我在一個視圖中使用偵聽器,該視圖在焦點到子組件時未初始化?
主叫從VM邏輯:
public class CLUViewModel : ViewModelBase
{
#region Properties
private RelayCommand _manageOwnersDialogCommand;
public ProgressDialogViewModel ProgressDialogVM;
#endregion
public CLUViewModel()
{
ProgressDialogVM = new ProgressDialogViewModel(string.Empty);
}
#region ManageOwnersDialogCommand
public ICommand ManageOwnersDialogCommand
{
get
{
return _manageOwnersDialogCommand ??
(_manageOwnersDialogCommand = new RelayCommand(param => OnManageOwnersDialogShow()));
}
}
private void OnManageOwnersDialogShow()
{
var dialog = new ManageOwnersDialog();
var vm = new ManageOwnersViewModel();
dialog.DataContext = vm;
if (!dialog.ShowDialog().Value) return;
var ownersRequiringCleanup = GetOwnersRequiringCleanup(vm);
if(ownersRequiringCleanup.Count < 1) return;
ProgressDialogVM.ClearViewModel();
ProgressDialogVM.TokenSource = new CancellationTokenSource();
ProgressDialogVM.ProgressMax = ownersRequiringCleanup.Count*2;
RaiseOwnerCleanupStartedEvent();
var taskOne = Task.Factory.StartNew(() => OwnerCleanupService.DoOwnerCleanup(ownersRequiringCleanup, ProgressDialogVM));
taskOne.ContinueWith(t => RaiseOwnerCleanupEndedEvent(), TaskScheduler.FromCurrentSynchronizationContext());
}
private List<Owner> GetOwnersRequiringCleanup(ManageOwnersViewModel vm)
{
var ownersRequiringCleanup = new List<Owner>();
// using DB to determine cleanup
// Proprietary code removed for this discussion
return ownersRequiringCleanup;
}
#endregion
#region Events
public event EventHandler OwnerCleanupStarted;
public event EventHandler OwnerCleanupEnded;
public void RaiseOwnerCleanupStartedEvent()
{
if (OwnerCleanupStarted == null) return;
OwnerCleanupStarted(this, new EventArgs());
}
public void RaiseOwnerCleanupEndedEvent()
{
if (OwnerCleanupEnded == null) return;
OwnerCleanupEnded(this, new EventArgs());
}
#endregion
}
我有,他們的各種虛擬機做出的家長電話(樹形視圖內)等幾個控制這個同樣的問題,即父引發事件。
我一直在學習這一點,而我在VM方面使用的一些事件是我之前對事物工作原理的理解。我應該把這個事件稱爲一個事件,引發到我的觀點,然後開始一個RountedEvent
泡泡到適當的水平?我是否陷入強結合與弱結合的陷阱?
編輯:解決父/子TreeView問題被看到。主 - 細節模式意味着我一直在訪問不可見或從未加載過的細節視圖。現在最初的問題仍然是null的發生。有沒有更好的方法從VM回調查看UI相關的問題,View DataContext不會有困難?
CLUViewModel的實例是否引發與您的MainWindow的DataContext相同的實例?如果不是,我會爲其他Window/UserControl創建一個新的ViewModel類,而不是讓多個Views具有相同的ViewModel。如果是,那麼當ViewModel可以非常容易地打開ProgressDialog本身時,我不明白爲什麼你要在ViewModel中的事件視圖中註冊事件處理程序。 –
我提供了一個關於OwnerCleanup事件的蒸餾模型,使它更容易閱讀,並儘可能小,同時仍然會產生錯誤。進度對話框是可以從應用程序中的幾個點使用的東西,我希望它可以由樹上的任何一個孩子統一調用。 –