Weird two controls / same datasource problem - winforms

This is using winforms.
I have a listbox and a combo box, both tied to the same datasource, same display members, same value members. All is bound just fine and the items show up in both the controls.
The problem is when I change a selection in one control, it moves to the same index in the other control. I don't have any events tied to either control. It is just happening on its own. Has anyone ever run into this?

This is because both the controls share the same BindingContext/CurrencyManager. Controls inherit the BindingContext from their container control. A BindingContext maintains only one CurrencyManager per DataSource. If you want to have two different CurrencyManagers, you need to have two BindingContexts.
So when once of the controls selection is changed, currencyManagaer.Current gets updated. This affects all the controls that share the same DataSource.
Instantiate a new BindingContext and assign it to the BindingContext property of one of the ComboBoxes:
comboBox2.BindingContext = new BindingContext();
This should solve the problem.

The datasource is a separate object. When one of the controls changes the datasource active row it sends out an update notification to the other controls to move accordingly. This is normal and expected behavior.
The idea behind it is to simplify navigating record sets while keeping all the bound controls in sync.
If you don't want that, use two datasources tied to the same underlying data.

I think that might be intended to be a feature. For Master/Detail type forms.

Related

Custom Items control Approach

I need to build a custom items control in WPF, where the user can drag/drop the items. Normally I would just maintain a list of view models and use a data template to define how the items should be displayed (in this case, a button). But I am concerned that this will make the drag/drop difficult as the ItemsSource objects will be view model objects , not the actual button.
My other potential approach is when an object is added to the ItemsSource, create a button in c# and add it manually, that way I can access the button directly to do drag/drop.
What would your advice be?
I have solved my issue. I found a way to get the control being render from the data template

How to refresh a WPF subtree without knowing what is in the subtree (Especially all bindings that only depend on converter rather than source value)?

Background:
I use converters to acquire values for most of my binding statement because the bindings are so complicated that even multi-binding cannot satisfy. I have to calculate the value in the converters and return the value. Also I use OneWay or OneTime binding just to show the correct value. When user changes a value, I use Handlers to set the value. The Handlers are also complex program which cannot be simply replaced by TwoWay or OneWayToSource binding. Actually in this case the DataContext does not have any meaning. I use converters. Another reason of using converters is that all Controls are loaded dynamically using many DataTemplates and it's hard to create dynamic DataContext for each Controls in each DataTemplate.
With above background, my application works fine. I'm looking for solutions for our new problem below.
I have many group of Buttons each represent a warehouse containing different type of items.
When double-click a Button, a detail window pops up and user can modify the items. Those items can be represented by CheckBox, Combobox, TextBlocks, TextBox, etc.
For user's convenience, I duplicated some of the frequently-modified Controls from the popup window onto the Button itself (WPF allows Button to contain sub-controls), so that user can directly modify the items without double-click and popup the detail window.
Each Button could contain unknown number of sub-controls such as CheckBox, Combobox, TextBlocks, etc. Here "unknown" means that in the future developer can duplicate any controls onto the Button if the Controls for those items are deemed frequently-modified.
Everything works fine so far.
When user modifies an item in the popup window and closes the window, I used to reload the DataTemplate for the whole window so that everything is refreshed and the controls duplicated onto the Button can synch up with the value modified from inside the popup window.
Everything still works fine so far.
The problem happens when the application runs on machine with slow hardware, where performance is an issue. On a much slower machine, reloading the whole DataTemplate for the whole application that contains many Buttons is quite slow.
So I'm looking for ways to just refresh the Button that is double-clicked, not all Buttons. However, I searched a couple of days and could not find ideal solution of refreshing a WPF sub-tree.
I tried to travel the sub-tree of the Button to assign null to the DataContext property and then assign back the old DataContext, but the binding seems not triggered and the converters were not called.
I saw someone suggested to use something like below:
((ComboBox)sender).GetBindingExpression(ComboBox.ItemsSourceProperty)
.UpdateTarget();
That demands that I know the Control and its property that has bindings. I think I can do the same for all possible Controls and properties but it does not seem a future-proof solution.
Anybody knows an effective way of refreshing a WPF sub-tree without knowing what is in the sub-tree?

Silverlight How to load a usercontrol in a page based upon a listbox selection

I am trying to work though the best approach to accomplish the following. Within a page I have it divided into two section. On the left a listbox and the right is empty. (Grid etc). What I would like to accomplish is when an item is selected from the listbox a different user control loads in the right panel. For example if I have three items (one, two three) selecting one would load a red user control, two would load a blue user control and three a green user control.
I was taking this approach since Content Template / Data template selectors are not available in SL. However if anyone has another suggestion I would be grateful for your thoughts.
I'm creating this with MVVM in mind and traditionally I have managed this within the code behind of the user control however I have seen mention of how this could be managed within the ViewModel as well.
Any suggestions or guidance on a best approach is always appreciated.
Cheers
You can bind both listbox selected item and user control visibility properties to the same property in the viewModel.
Then just use a valueConverter for each user control to switch on/off the visibility.
Please tell me if i should elaborate/add a code sample.

WPF - Need an event for when VirtualizingStackPanel creates Items for ListView

Is there any way to tell when the containers are finished being made for a ListView?
A detailed explanation of what I've done so far
I have a ListView control that has a DataTemplate in one of its columns that contains a CheckBox Control.. I've figured out how to access the CheckBox dynamically using the object that the ListView is bound to.
ListViewItem lItem = (ListViewItem)ListView.ItemContainerGenerator.ContainerFromItem(trackToHandle);
CheckBox checkBoxToHandle = FindChild<CheckBox>(lItem, "CheckBox");
The problem is that the CheckBoxes "reset" (become unchecked) whenever I scroll too far or whenever I sort the columns.
I figured out this was because the VirtualizingStackPanel was only spitting out containers for those ListViewItems that were visible (or almost visible)..
And because the CheckBox is inside a DataTemplate that is defined in the XAML it gets thrown away everytime it goes out of view or when the list is sorted.
I got around this by creating a separate list of CheckBoxes and using the actual CheckBoxes "click" event to change the state of the corresponding CheckBox in my list.. then made a little method to go change the state of all the visible CheckBoxes whenever the user scrolls... as a result it appears like it should have in the first place.
Except when I sort the columns.
I tried making it re-do the CheckBoxes (like before) right after it'd sorted a column but it didn't work.
My best guess is that it doesn't immediately make the containers after I sort..
Is there any way to tell when the containers are finished being made for a ListView?
If you bind your checkboxes IsChecked property to a boolean property on your data context, then you will not have this issue.
The whole purpose of the VirtualizingStackPanel is reduce memory usage by not creating ListItem's unless needed.
In effect, you need to move the data side of the checkbox away from the control.

Enable or Disable multiple controls in Silverlight

What is considered the best way of enabling or disabling multiple controls in Silverlight at the same time (textbox, combobox, autocompletebox and the like)?
I suppose I could bind the "IsEnabled" property of each control to a boolean property. That property only exists for interactive controls and not textblocks.
I could loop through the children recursively and set their properties appropriately, but that seems inelegant.
Ideally, I'd like to just set some disable-like property on the parent container of the controls, giving even the TextBlocks a disabled look similar to a Windows form.
Is there a way to just disable the parent container?
Use the ContentControl Silverlight provides.
<ContentControl x:Name="GroupOfControls" >...Your controls...</ContentControl>
//Enable and Disable
GroupOfControls.IsEnabled = false;
You could use a ViewModel approach similar to the answer in StackOverflow 1545844
By having a calculated IsEnabled property you can then bind the elements in the View which should be controled by this property.
Usually I always create a ControlHandler Class that does all the updates on my controls. (Just to separate concerns)
Recently we had to reset all controls on the form and didn't want to loop through every single control.
All control-related data logic gets updated in the ControlHandler class.
We then only apply the values appropriate values / properties onto our controls.
This is a workaround but worked pretty well and also cleanly for us.
There are, of course, better ways to solve that..
I was looking into disabling multiple controls when fetching data from a web service.
The BusyIndicator control got me what I needed with very little effort.
Maybe it'll be a good enough solution for others as well.
Wrap with UserControl and set its IsEnabled property.
...

Resources