私の WPF アプリケーションには、アイテムを含むリストボックスがあります。リストボックスは、XAML から xmldataprovider を介して設定され、リストボックスの Itemssource プロパティにバインドされます。
XAML から、コマンドをリスト ボックスにバインドするには、次のようにします。
<ListBox.CommandBindings>
<CommandBinding
Command="{x:Static local:mainApp.MyCmd}"
CanExecute="CanExecute"
Executed ="Executed" />
</ListBox.CommandBindings>
しかし、コマンドを各リストボックス項目にプログラムでバインドする方法がわかりません。どうやってするの?
前もって感謝します。
コメントとして投稿しないことで最初に申し訳ありません。これをすべてコメントに入れることはできません。
わかりました、はい、ICommandSource の Executed プロパティと CanExecute プロパティを使用していませんが、それらをカスタム クラスに登録して実装しました (xaml でもコメントされています)。カスタム クラスではなく routedCommand で指定しました。ウィンドウのコンストラクターで次のように指定しました。
WinMain コード ビハインド:
public WinMain()
{
InitializeComponent();
// Command binding. If I don't do this Executed and CanExecute are not executed
CommandBindings.Add(new CommandBinding(rcmd,
CommandBinding_Executed, CommandBinding_CanExecute));
}
そして、これらのメソッドを WinMain コード ビハインドにも実装します。
// ExecutedRoutedEventHandler
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Do stuff
}
// CanExecuteRoutedEventHandler
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// cBgWorkers is a class that check if a background worker is running
e.CanExecute = !cBgWorkers.isRunning;
//if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;
}
WinMain XAML では、次のようにコマンドを呼び出します。
<Classes:CommandListBox x:Name="LayoutListBox"
Command="{x:Static local:WinMain.rcmd}"
... >
<...>
</Classes:CommandListBox>
また、カスタム クラス CommandListBox には CanExecuteChanged があり、バックグラウンド ワーカーが終了したかどうかに応じて、コントロールを有効または無効にしたことがわかります。
private void CanExecuteChanged(object sender, EventArgs e)
{
this.Enabled = !cBgWorkers.isRunning;
}
しかし、カスタム クラスでは、OnSelected というイベント ハンドラを実装していません。
実装しなくても、カスタム コントロールの呼び出しコマンドが実行され、CanExecute メソッドに到達し、バックグラウンド ワーカーが終了しているかどうかに応じて、CanExecute が正しい値 (true または false) を取得し、CanExecute がその値を変更すると、カスタム コントロールの CanExecuteChanged が発生します。 . バックグラウンドワーカーが開始すると無効になりますが、終了すると有効になりません。バックグラウンド ワーカーが終了すると、CanExecuteChanged が実行され、this.Enabled が正しい値 (true) を取得していることがわかりますが、UI で何らかの理由で、正しい値を取得しているにもかかわらず、RunWOrkerCompleted (バックグラウンドで) にもかかわらず、コントロールは無効のままです。 worker) CommandManager.InvalidateRequerySuggested() で強制的に UI を更新します。
行のコメントを外すことでこれを解決します。
if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;
CanExecute メソッドで。何が起こるかわかりません。
もし私があなたの言うことをするなら、それをする必要はありません:
CommandBindings.Add(new CommandBinding(rcmd,
CommandBinding_Executed, CommandBinding_CanExecute));
CommandBinding_Executed および CommandBinding_CanExecute の実装。私は正しいですか?
しかし、これらのメソッドを削除すると、どこで this.enabled = !cBgWorkers.isRunning を設定できますか?
カスタム コントロールの isEnabled プロパティを WPF で自動的に設定したいと考えています。これを行う方法?
前もって感謝します。
アタッチされた動作についてあなたが言う記事を適用して、いくつかの変更を加えてリストボックスに適応させています。うまくいかないか、何か間違ったことをしているのかもしれません。私が望むのは、長いタスク (バックグラウンド ワーカー) が実行されているときに、ListBox メンバー (listBoxItems) を選択できないようにすることです。したがって、私が変更した記事の方法の1つは次のとおりです。
static void OnListBoxItemSelected(object sender, RoutedEventArgs e)
{
// Only react to the Selected event raised by the ListBoxItem
// whose IsSelected property was modified. Ignore all ancestors
// who are merely reporting that a descendant's Selected fired.
if (!Object.ReferenceEquals(sender, e.OriginalSource))
return;
ListBoxItem item = e.OriginalSource as ListBoxItem;
if (item != null)
{
// (*) See comment under
item.IsEnabled = !cBgWorkers.isRunning;
if (!cBgWorkers.isRunning)
{
item.BringIntoView();
}
}
}
(*) cBgWorkers は、いくつかのメソッドとプロパティを持つ public static Class です。プロパティの 1 つは、バックグラウンド ワーカーが現在実行されていないことを示す isRunning です。次に、バックグラウンドワーカーが実行されていない場合、リストボックスメンバーを有効にする必要があります。それ以外の場合は無効にする必要があるため、ユーザーがリストボックスアイテムをクリックしても、以前に無効にしたため、現在のページが別のページに変更されません (各リストボックスアイテムには1つが添付されています)私のメインアプリケーションのページ)。
バックグラウンド ワーカー (bw) の 1 つまたはすべてが実行されていて、リストボックス アイテムを選択すると、すべて問題ありません。bw が実行されているため、リストボックス アイテムは無効になり、現在のページを別のページに変更することが回避されます。もちろん、リストボックス項目 (またはリストボックス項目) を無効にすると、無効になっているため再度選択できません。それが私の問題です。bw の実行中に無効になったリストボックス項目を bw が終了したときに、それらは再び有効になります。残念ながら、WPF によって自動的に行われるわけではなく、コマンドにはこの利点があります (コントロールは WPF によって自動的に更新されます)。それで、bwが実行されているかどうかにかかわらず、リストボックス項目を無効/再有効化する方法は?
私が知り、見る限り、アタッチされたビヘイビアーの利点の 1 つは、アクションを常に呼び出すわけではないため (選択などのアクションが生成された場合のみ)、より効率的であると考えられることです。コマンドは、コントロールにバインドされたアクションを実行できるかどうかを常に (頻繁ではありませんが) チェックしています (実行できる場合、WPF は自動的にコントロールを有効にし、そうでない場合は無効に見えます)。
ありがとう。