I have buttons on my Silverlight page where the opacity is bound to one of two properties on my ViewModel. I'm using the button command that changes the properties, in theory to affect all buttons bound to that property, but the only control that gets affected is the button that initiates the command (any one of them).
Any ideas on why the additional bindings don't work?
The whole thing is actually a little more complex where the buttons are on a Control with the bindings as DependencyProperties mapping back to the VM, and the bound properties are going through a ValueConverter.
It sounds like you need to raise the INotifyPropertyChanged.PropertyChanged event for the properties that are changing. This will let the controls that are bound to them know that there is a change and that they need to come back and get the latest value.
I found the problem. The opacity binding wasn't working, but what was happening was the button was disabling itself based on the predicate I had set in the RelayCommand. It looked like the effect I wanted, but only affected the button being pressed because each button was bound to a seperate ICommand.
I changed it to remove change the binding from the OpacityProperty to the IsEnabledProperty, and removed the predicate from the RelayCommand declaration. It all works now as intended.
I don't know why the button would change to a disabled view when it checks the predicate (and finds it false), but never change back if the condition changes. Odd.
Related
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?
I have a button that I want to disabled in some cases. To determinate that, I use the selection of many controls in the view. For simplify in this question, two comboBox.
So the IsEnabled depends on the combiation of the information in this two controls, I need to evaluate the new state when change one of them. How can I do that? I know that I need a multi value converter to determinate if the button is enabled or not, but I don't know how to execute the converter when the selection in one of the combobox is changed.
EDIT:
When I have said before Multi value converter I wanted to say multi binding.
Perhaps I have not been very clear. I want the following:
1.- In the beginning the button is disabled and the two comboBox have not any item selected.
2.- When I selected an item in one of the comboBox, I need to execute the multi binding that is used to set the IsEnabled property of the button.
And repeat the process when I selected a new item in any of the comboBox.
The problem that I have is that I don't know how to say to the button that when I change the selection in any of the comboBox, the button need to execute the multi binding to determinate the value of the IsEnabled property.
but I don't know how to execute the converter when the selection in one of the combobox is changed.
As long as the values you're binding to are either DependencyProperty values or part of a class that (properly) implements INotifyPropertyChanged, this will happen automatically. You shouldn't need to do anything to update the values.
Just make sure the bound values notify as if they were used directly, and WPF will handle this when using an IMultiValueConverter just fine.
I have an ObservableCollection where T: INotifyDataErrorInfo. If I use the DataGrid in edit mode, and there is an error on the object, beside the exact column displaying a red border, the BACKGROUND of the ENTIRE ROW goes red.
I want the same functionality, but in readonly mode as well! The problem is, the DataGrid doesn't listen for ErrorsChanged event unless it goes into edit mode. How can I fix it? Do I have to subclass DataGrid? (I'd prefer not to, I'd rather use Styles or Behaviors) Where can I access the style of the row's background?
EDIT:
I've tried two new things:
I've subscribed to the datagrid's RowLoading event, and subscribed to the Row's Loaded and the DataContext's ErrorsChanged event from there (and unsubscribed on RowUnloading), and tried setting the VisualState of the row from these event handlers based on the validity of the DataContext. However, since setting the visual state doesn't change the actual state of the control so when it has to change states (for example on mouseover or selection) it changes back to Valid.
Using the trick I've learned from ComboBoxes (see here), I've tried to bind the DataContext to the DataGridRow.Tag, using row.SetBinding(DataGridRow.TagProperty,new Binding()); (since the Source is the DataContext and the path is the entire object), but absolutely nothing happened, like contrary to my earlier findings with ComboBox controls doesn't necessarily listen for Validation on Every DependencyProperty.
So it's getting less likely that there is a practical solution. Any thoughts?
Have a look at the following question, it might help
C# Silverlight Datagrid - Row Color Change
I'm trying to achive displaying the RowDetailsTemplate of a Silverlight DataGrid depending on a bool Property, bound to a CheckBox Control's IsChecked Property. Insinde of my RowDetailsTemplate there is a single custom UserControl, containing further Controls.
Since the DataGrid only allows a global setting (RowDetailsVisibilityMode) Some code-behind is needed. I've implemented a solution based on Rorys Reply (and using a behaviour-technique) which actually works.
Unfortunately, The DataGrid doesn't remember the individually shown or hidden Rows on sorting. The checkbox remains selected, but the Row collapses. Further, no event like "OnAfterSort" or something similar seems to exist, where i could "Refresh" the visibility settings in a loop.
Another idea was to bind the Visibility of my custom Details-UserControl to the CheckBox bound value. This actually works (when settings RowDetailsVisibilityMode to "Visible"), but I'm not able to get rid of this weird behaviour: When the CheckBox is checked, the Detail Template expands and the detail UserControl appears. Nice. When the CheckBox is unchecked again, the UserControl disappears (Visibility is set to Collapsed) but the Row doesn't collapse and the blank space remains (as it would be set to Hidden not Collapsed).
Do you have any ideas?
I hope it's ok I didn't post any code samples, the implementation is pretty easy and I believe that the problem doesn't actually lie in a coding mistake i made. You can setup a simple DataGrid quickly like in this perfect MSDN Example. Starting from here, it's easy to test both described behaviours!
Really big thanks in advance,
- Thomas
I've got a xaml TabControl and on one page, there are 3 RadioButtons each bound to a different property on the selected value of an adjacent ListView. After switching between selected items in the ListView, my radio buttons seem to forget they're bound and don't refresh.
So watching it in the debugger, when I switch to a new selected item, I see the non user code first checking the value on all 3 properties, then only the first two, and eventually only the first. However, if I change the tab and change back, it seems to give me another few uses.
The binding itself is fairly straightforward. a TwoWay binding of a bool property to IsChecked. It's 4 levels deep (Path=DataModel.Selected.A.B), but I have other things at the same depth that work fine.
Is this something people have heard about and know what might be going on? Or if the binding is somehow getting forgotten, is there a way to explicitly remind the xaml?
It is possible to manually update bindings like this:
TestCheckBox
.GetBindingExpression(CheckBox.IsCheckedProperty)
.UpdateTarget();
That being said, I don't have 100% confidence that this will correct your underlying issue. I haven't had this sort of issue before with WPF bindings, but I have had a couple weird issues with the tab control.
This is apparently somewhat of a known issue:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/8eb8280a-19c4-4502-8260-f74633a9e2f2/
In short, a RadioButton (through .Net 3.5sp1) somehow kills bindings of other RadioButtons when when it's checked while trying to uncheck any other buttons. The simple fix (read: hack) is to assign each radiobutton a different GroupName and then they don't try to mess with eachother
Another way to resolve this issue is to fake up a list of properties in a ListBox and have the ListBoxItem template be a radiobutton.