我有這個有趣的案例: 一個相當大的應用程序的頁面有它自己的ViewModel。部分數據來自完全不同的經理類。我的ViewModel可以訪問這些數據。每次經理類更新一個值,它都會發送一個調解器消息。 ViewModel獲取消息並調用OnPropertyChanged(nameof(ManagerdataData))
。 ManagerData財產只有一個獲得者得到Manager.Data
。所以頁面會更新它的內容。該系統目前運作良好。ViewModel的第二個視圖不刷新
現在我打開一個MessageBox事物(這是一個System.Window
),得到MessageBox.DataContext = this.ViewModel
。對於用戶界面,它也適用。我的所有ManagerData都被加載並顯示在differend Bindings中。但是: OnPropertyChanged似乎沒有效果。 頁面每次都會刷新這個特殊的Mediator-Message來自Manager,然後ViewModel會觸發OnNotificationChanged,綁定值會重新加載並從Manager中獲取新數據。但是MessageBox不具有相同的ViewModel。
有沒有人有這樣的想法?
我想,也許這是我的ViewModel的另一個實例(副本)。所以我問是否顯示一個彈出窗口,獲取正確類型的最頂層窗口並嘗試調用包含這些OnNotificationChanged值的方法。首先它因爲我錯誤的線程而崩潰。使用調度程序會導致整個應用程序凍結。
有什麼想法?複製代碼...不容易,因爲該項目是相當大的...
編輯: 好了,所以這裏的代碼:
視圖模型:
// Inside the constructor. Registers for Mediator-message. The manager sends it when a value is set.
Mediator.Register(MediatorMessage.BackendServerCheckRefreshed,() => RefreshServerCheckUi());
// Method of the Mediator Message
public void RefreshServerCheckUi()
{
OnPropertyChanged(nameof(BackendServers));
OnPropertyChanged(nameof(BackendServersCommonStatus));
}
// Properties that get stuff from the manager
public BackendServerStatus BackendServersCommonStatus
{
get
{
return backendServerManager.CommonStatus;
}
}
public BackendServer[] BackendServers
{
get
{
return backendServerManager.BackendServers;
}
}
這樣做的UI頁面:
<!--Style definition-->
<Style TargetType="Image" x:Key="BackendServerAvailability">
<Style.Triggers>
<DataTrigger Binding="{Binding BackendServersCommonStatus}"
Value="{x:Static server:BackendServerStatus.NotAvailable}">
<Setter Property="Source" Value="inactive.png" />
</DataTrigger>
<DataTrigger Binding="{Binding BackendServersCommonStatus}"
Value="{x:Static server:BackendServerStatus.Available}">
<Setter Property="Source" Value="active.png" />
</DataTrigger>
</Style.Triggers>
<Style.Setters>
<Setter Property="Source" Value="default.png" />
</Style.Setters>
</Style>
<!--Image-->
<Image Style="{StaticResource BackendServerAvailability}" />
這個綁定工程。當值刷新時,它發送調解器消息,這調用OnPropertyChanged
,然後圖標獲取其圖像。
現在棘手的問題:
// This is how I call the MessageBox from the ViewModel
this.MessageService.ShowBackendServerCheckInfo(this);
的MessageBoxService:
// All MessageBoxes are created like this.
public void ShowBackendServerCheckInfo(ViewModel viewModel)
{
Action action = new Action(() =>
{
var args = new MessageBoxEventArgs()
{
View = new BackendServerCheckMessageBox(),
ViewModel = viewModel
};
OnNewMessageBox(this, args);
});
this.ShowMessageBox(action);
}
// And then called like this:
private void ShowMessageBox(Action action)
{
/* We need to create the view in the same thread as main application. */
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
終於在MainWindow.xaml.cs:
private async void MessageService_OnNewMessageBox(object sender, MessageBoxEventArgs e)
{
// Some Semaphore work here..
var messageBox = e.View;
messageBox.DataContext = e.ViewModel;
messageBox.Owner = this;
messageBox.ShowDialog();
// Release Semaphore
}
MessageBox的UI:
<ItemsControlItemsSource="{Binding BackendServers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Stackpanel>
<TextBlock Text="{Binding Url}" />
<TextBlock Text="{Binding Port}" />
<Image Style="{StaticResource BackendServerAvailability}" />
</Stackpanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!--Buttons-->
<Stackpanel>
<Button Style="{StaticResource SimpleButtonStyle}"
Command="{Binding CloseBackendServerCheckCommand}"
CommandParameter="{Binding ElementName=BackendServerMsgBox}">
<TextBlock Foreground="White" Margin="2" FontSize="14"
Text="{x:Static const:Resources.ButtonOk}" />
</Button>
<Button Style="{StaticResource SimpleButtonStyle}"
Command="{Binding RestartBackendServerCheckCommand}">
<TextBlock Foreground="White" Margin="2" FontSize="14"
Text="{x:Static const:Resources.ButtonRefresh}" />
</Button>
</StackPanel>
所以這是所有相關的代碼。當綁定不起作用時,我根本沒有任何價值,按鈕也不起作用。關閉按鈕將其作爲參數發送其Window
,然後args-Window-Object將被關閉。如果綁定和東西不起作用,什麼都不會發生。 我修好了。現在我看到了我所有的價值。但是,當backgroundcheck發送一條消息,指出某個服務器不可用時,Popup-Image在應用程序圖像不會刷新時不會刷新。
我的猜測是,通過所有的東西作爲EventArgs可能會做一些副本,所以綁定到正確的ViewModel實例會丟失...所以我會爲這個彈出窗口,並直接在我的ViewModel創建它。無論如何,它比任何「平常」的彈出式菜單都要多,只是向你拋出一些東西,而你用「好吧」點擊它。在這種情況下更復雜。
編輯2: Aaaand直接從ViewModel調用MessageBox並沒有改變一件事。它不起作用。這是一個有多個綁定視圖的問題嗎?
EDIT3: 好吧,它實際上不工作,當我有彈出和重新設置的DataContext從視圖模型的實例。所以我必須找到一個很好的方式來獲得或保持實例...
視覺工作室的輸出窗口可能會給你我想的答案。沒有足夠的代碼來複制行爲,我們無法幫助您。 – nkoniishvt
什麼可能在輸出窗口中?我認爲這可能是更多的理論問題:你認爲viewmodel實例只是複製到datacontext? – ecth
*如果*您已準確地表示將視圖模型分配給MessageBox.DataContext的方式,則複製事件似乎不太可能。但是對於那些說「實際上我不會告訴你我的任何代碼,請重新構造它所做的一切」的人來說,這很難說。發生了什麼顯然是可能的,因爲它正在發生。我的第一個猜測是,你的問題在於你完全排除的東西,因爲你知道它不可能是這樣。這可能不是異國情調。這可能是一個常見的錯誤,您可以通過遵循從點A到點Z的所有內容來找到。 –