Note that there are some explanatory texts on larger screens.

plurals
  1. POAdding programatically a command to a listbox in WPF
    text
    copied!<p>In my WPF application there is a listbox with items. The listbox is populated via a xmldataprovider from XAML and then binding it to Itemssource property of the listbox.</p> <p>Well, from XAML, I bind a comand to the listbox by doing:</p> <pre><code> &lt;ListBox.CommandBindings&gt; &lt;CommandBinding Command="{x:Static local:mainApp.MyCmd}" CanExecute="CanExecute" Executed ="Executed" /&gt; &lt;/ListBox.CommandBindings&gt; </code></pre> <p>but I don't know how to programatically bind a command to each listboxitem. How to do it?</p> <p>Thanks in advance.</p> <hr> <p>First sorry by not posting it as a comment. I can't put all this in a comment.</p> <p>Ok, yes I am not using the Executed and CanExecute properties of the ICommandSource despite I have registered and implemented them in custom class (in xaml they are commented too). I have specified them in routedCommand but not in custom class, I have done it in the constructor of the window by doing this:</p> <p>WinMain code behind:</p> <pre><code>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)); } </code></pre> <p>and then I implement these methods in WinMain code behind too as it:</p> <pre><code>// 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; } </code></pre> <p>and In WinMain XAML I invoke the command like this:</p> <pre><code>&lt;Classes:CommandListBox x:Name="LayoutListBox" Command="{x:Static local:WinMain.rcmd}" ... &gt; &lt;...&gt; &lt;/Classes:CommandListBox&gt; </code></pre> <p>And in my custom class CommandListBox I have a CanExecuteChanged in which you can see I enabled or disabled the control depending on whether the background worker is finished or not:</p> <pre><code>private void CanExecuteChanged(object sender, EventArgs e) { this.Enabled = !cBgWorkers.isRunning; } </code></pre> <p>but in custom class I haven't implement the event handler you say, OnSelected.</p> <p>WIthout implementing it all goes ok, the custom control invoke command, and CanExecute method is reached, and CanExecute gets correct value, true or false depending on background worker is finished or not, and the CanExecuteChanged in custom control is raised when CanExecute changes its value. When background worker starts it gets disabled but when it finished it doesn't get enabled. I have debugged, and when background worker finishes I can see CanExecuteChanged is executed and this.Enabled is getting correct value (true) but for some reason in the UI the control continues disabled despite it gets its correct value and despite in RunWOrkerCompleted (in background worker) I force to update UI with CommandManager.InvalidateRequerySuggested().</p> <p>I solve this by uncomment line:</p> <p>if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;</p> <p>in CanExecute method. I don't understand what happens.</p> <p>Then If I do what you say It is not necessary to do it:</p> <pre><code> CommandBindings.Add(new CommandBinding(rcmd, CommandBinding_Executed, CommandBinding_CanExecute)); </code></pre> <p>and CommandBinding_Executed &amp; CommandBinding_CanExecute implementations. Am I right?</p> <p>but if I remove these methods where can I set this.enabled = !cBgWorkers.isRunning ?</p> <p>I would like WPF to set automatically isEnabled property for my custom control. How to do this?</p> <p>Thanks in advance.</p> <hr> <p>I am applying the article you say about attached behaviors with a few changes to adapt it to my ListBox. It doesn't work well or perhaps I am doing something wrong. What I want is avoid that ListBox members (listBoxItems) can be select when a long task (background worker) is running. So one of the method of the article that I have modified is:</p> <pre><code> 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(); } } } </code></pre> <p>(*) cBgWorkers is a public static Class that has some methods and properties. One of the properties is isRunning that indicates no background workers is currently running. Then If no background workers is running, listbox members have to be enabled otherwise they have to be disabled so when user clicks over one listbox item the current page don't change to another one because I disabled it before (each listBox items has attached one page in my main application). </p> <p>When one of the background workers (bw) or all are running and I select listbox item all is ok: listbox item is disabled because there are bw running and it avoid tho change the current page to another one. Of course, If I disabled the listbox item (or listbox items) I can't select it again because it is disabled and that is my problem, because I want that when bw finish the listbox items that have been disabled while bw were running, they get enabled again. Unfortunately with attached behavior as I see it isn't done by WPF automatically and commands have this advantage (controls update automatically by WPF). so, how to disabled/re-enabled listbox items when bw is running or not respectively?</p> <p>As far as I know and see, one advantage of attached behaviors is that I think it is more efficient because they are not invoking actions constantly (only when the action, for example, selection, is produced). Commands are constantly (not often) checking if actions binded to controls can be executed (so If they can be executed, WPF automatically enables controls otherwise they appear disabled), right?</p> <p>Thanks.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload