私はDataGrid
に基づいてAppointment
というオブジェクトのビューを持っています。ユーザーが行をダブルクリックすると、モデルウィンドウが開き、クリックされた予定を表示/編集します。私はLeftDoubleClick
マウスイベントにバインドされた以下のコマンドでそれを行います。バインディングの動作とコマンドが正しく呼び出されます。viewmodelのプロパティを変更すると、ビューが更新されないのはなぜですか?
_doubleClickCommand = new DelegateCommand<AppointmentRowViewModel>(async p =>
{
if (BossViewModel.ShowModalCommand.CanExecute(null))
{
var modal = new AppointmentFormWindow();
await modal.ViewModel.Populate(p.Id, Cts.Token);
BossViewModel.ShowModalCommand.Execute(modal);
}
},
p => true
);
選択された項目とコマンドパラメータ、p
は、プロパティのみゼロロジックと、AppointmentRowViewModel
、AppointmentDto
オブジェクトの純粋なプレゼンテーションモデルです。
BossViewModel
は、MainWindow
のビューモデルであり、どのビューが表示されるかを管理します。この場合は、モーダルとメッセージボックスを表示します。メッセージボックスにはオーナーウィンドウが必要なので、この責任を置いています。これはビューを認識している唯一のビューモデルです。 MainWindowViewModel
から他のウィンドウを開いて管理するだけでも意味がありました。
したがってDoubleClickCommand
は、開きたいウィンドウのインスタンスを作成し、そのウィンドウのXAMLはこの場合はAppointmentFormViewModel
を割り当てます。コマンドは、予定をロードし、それのviewmodelにマッピングすることのviewmodelにPopulate
を呼び出します。
_showModalCommand = new DelegateCommand<IModal>(async modal =>
{
modal.ViewModel.BossViewModel = this;
modal.ShowDialog();
},
a => !ModalOpen
);
:
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnAllPropertiesChanged()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
}
その後BossViewModel.ShowModalCommand
は次のようになります。私はこのようなINotifyPropertyChanged
を使用
public override async Task Populate(int? entityId = null, CancellationToken cancellation = new CancellationToken())
{
if (entityId.HasValue)
{
await _apptService.Load(entityId.Value, this, cancellation);
}
IsInitialized = true;
OnAllPropertiesChanged();
}
すべて正常に動作し、予定はに既に割り当てられているviewmodelにマップされたDBからロードされます。モーダルは開きますが、そのビューモデルは完全に埋め込まれており、フォームフィールドのどれもがviewmodelプロパティ値を反映するように更新されません。これは、私が新しい予定を作成しているかのようです。
私のすべてのデータバインディングを使用「モード=双方向
を、NotifyOnSourceUpdated = Trueの
」ので、私はのviewmodelに値を設定し、PropertyChanged
を上げると、ビューの要素を更新するだろうと期待しておりますが、ビューは、すべて完全に空白のまま。
更新: XAMLの抜粋は空白のままです。フォームにはキャプチャのみが正常に機能するため、バインドされたviewmodelプロパティはすべて有効な値を持ちます。
<Window.DataContext>
<vm:AppointmentFormViewModel />
</Window.DataContext>
.....
<TextBlock Text="Topic:" />
<TextBox Text="{Binding Topic, Mode=TwoWay}" />
<TextBlock Text="Venue: " />
<TextBox Text="{Binding Venue, Mode=TwoWay}" />
<TextBlock Text="Start Date: " />
<DatePicker SelectedDate="{Binding StartDate, Mode=TwoWay}" />
<ComboBox IsEditable="False" ItemsSource="{Binding TimeList}" SelectedItem="{Binding Path=StartTime, Mode=TwoWay}" />
<TextBlock Text="End Date: "/>
<DatePicker SelectedDate="{Binding EndDate}" />
<ComboBox IsEditable="False" ItemsSource="{Binding Path=TimeList}" SelectedItem="{Binding Path=EndTime, Mode=TwoWay}" />
....
<DataGrid x:Name="TheList" Grid.Row="1" ItemsSource="{Binding Attendees}"....>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding GivenName}" Header="Given Name" />
<DataGridTextColumn Binding="{Binding FamilyName}" Header="Family Name" />
<DataGridTextColumn Binding="{Binding Phone}" Header="Phone" />
<DataGridTextColumn Binding="{Binding EMail}" Header="Email" />
<DataGridTextColumn Binding="{Binding Position}" Header="Position" />
<DataGridTextColumn Binding="{Binding OrgName}" Header="Org." />
<DataGridTextColumn Binding="{Binding BranchName}" Header="Branch" />
</DataGrid.Columns>
問題は解決:突然、多くのコードの検査後、上記のコードの抜粋、およびいくつかのGitのロールバック用に編集し、問題のビューが正しく読み込まれます。私はそれがバインディングTwoWay
を作っていたと思うが、私が最初にそれをしたとき、それはうまくいかなかった。他の何かが間違っていたので、以下のコメントに答えるためにすべての手間を掛けながら、私は何とか何かを適切な状態に復元しました。
あなたの助言や助言をいただいたすべてのコメント者様、ありがとうございます。
ポストXAML(の一部)、および結合エラーの出力ウィンドウに求めますか。 –
UIスレッドからUI通知メソッドを呼び出していることを確認してください。ここには多くの非同期があり、UIスレッドで実行されないとUIの変更が失われる可能性があります。 –
また、VSのアプリケーション出力ウィンドウに、例外をスローしないバインディングエラーが表示されることがあります。それは有用な情報かもしれません。 –