Can the result of a MultiValueConverter be itself converted? - wpf

I have a form in my WPF application that I have to add an Edit button to. Right now, the form is always in edit mode and there is no "view mode". However, for various reasons, I need to keep the control in view mode until the user clicks an Edit button, and then hide the edit button and display a Save button in its place.
My form already has a bool DependencyProperty called CanModify, which is true when the user's permissions give them the right to edit the record being displayed in the form. I am adding a new bool DependencyProperty called InEditMode, which will default to false. Hiding and enabling the buttons is pretty straight forward, but I have this ComboBox control that I want to hide if the user can't edit the record, or if they can edit it and the form is in view mode. For that, I need to convert the result of ANDing the two bool properties together and then convert it into a Visibility value.
I've already got a class that implements IValueConverter and converts a bool into a Visibility. I've just written a class that implements IMultiConverter which takes an array of bools and ANDS them together (or ORs them, depending on the value of the parameter).
What I'd like to do is to take the result of the IMultiConverter and put it through the IValueConverter to convert the result into a Visibility. Can I do that? Or would I be better off doing the AND in the code behind to a new DependencyProperty?
Tony

You can indeed chain converters, my own example does not yet deal with MultiValueConverters but it shouldn't be too hard to implement a LinkedMultiValueConverter. One of the downsides of this approach is that you would have to recreate any converters you currently have to use the provided attribute.
git://github.com/pmacn/ValueConverters.WP8.git
or
https://github.com/pmacn/ValueConverters.WP8
and then you would do the following
<con:LinkedConverter x:Name="MyFancyLinkedConverter">
<con:BooleanInversionConverter />
<con:BooleanToVisibilityConverter />
</con:LinkedConverter>

You can't chain converters.
Instead change your MultiValueConverter to take a string parameter, "bool" or "visibility". Depending on the parameter return either a bool or visibility object

Because you can't chain converters, I added another boolean property to my class. I added methods to the two properties the new one is dependent upon that are called when they change. These recompute the value of the new property. I then used my original boolean to visbility converter to show or hide the control in question.

Related

how to bind button is enable property to a enum in wpf

i am using listView grouping based on an enum which {Updated and not Updated}. In my case, their is a button to call update I just want to disable if rows are in an updated group. See in the images.
The list that is present in updated section I want that the button should be disabled. I am using an example found in Here
IsEnabled={Binding ProperyNameOnYourViewModel, Mode=OneWay}
That will work assuming 1) your VM implements INotifyPropertyChanged and triggers appropriate event at the appropriate moment (typically, property's setter is responsible for that); 2) your control itself knows how to react on IsEnabled=false visually, i.e. changes color or whatever you like it to do.
Since you got an enum rather than bool, the easiest way to stick to the solution I've suggest is by extending your VM with yet another property, which recomputes boolean flag all the time. Then you might invoke PropertyChanged event not from your bool property (to which IsEnabled is actually bound), but from the enum property such that whenever it changes, WPF gets notified that boolean property has changed as well.
Otherwise, solve the problem with help of converters, which requires a lot more code.

How do I pass an extra variable to a a datatemplate

I have a DataTemplate(well two data templates) that I want to use as views for some
basic form viewmodels(that that contain a value and and boolean indicating whether I want to use the value).
I want to use the datatemplate(s) several times for separate form items. I think the right way to do this is to set it as the ContentControl's ContentTemplate (in that case it will have the same data context right?) but I also want to pass the label string and since the label string is part of the ui and doesn't change it seems wrong to put it in the viewmodel object. How do I give access of the label string to the DataTemplate instance?
Just like its name, a DataTemplate is used to template the Data... For example, if you have a class called MyItem which has a Name and Value and you want this shown in a specific way, you'll set a datatemplate for Item and use it whenever needed.
In your case, you're speaking about having very similar views, with only a minor change between them. This minor change (if I understood your question correctly) is not something that comes from the model or from the viewmodel but something which is entirely view-oriented (a different title for the page, for instance).
If you plan on using a different viewmodel for every view, and each viewmodel has a different purpose - I don't see a problem with adding a Title property to the VM and bind to that too (Remember, MVVM is a set of guidelines, not rules...)
If you still rather have it separated from the viewmodel, then you can use an Attached Property. Create an Attached Property called TemplateTitle, for instance, and have each contentcontrol in each view change it. The label, of course, will bind to that Attached Property.

Data binding: Different triggers for different purposes

I have a WPF MVVM data form window with data validation. A lot of the controls are text boxes. Currently, the data binding trigger is set to the default, i. e. loss of focus. This means that a field is only validated when it is likely to be filled out completely. So when deleting a number and typing another number, the transient empty value will not be displayed as input error.
But a drawback is that the Save button can only be enabled when the focus moves out of the text box. (No matter where, just out of the edited control. Assuming there is anything else focusable.) If this is the only change, the user waits for the Save button to be available and nothing happens. For the Save button, I'd like to use an immediate binding trigger. How can that be done?
Edit: Forgot to mention that my Save button (which uses ICommand) is only enabled when the input is determined modified and valid. So the data will remain unmodified until data binding updates it, and that won't happen until the focus moves to another control.
I actually had a similar question a while back and the solution I ended using was a custom DependencyProperty that kicked off a timer when a key was pressed, and only actually processed the PropertyChange notification if a specific time had passed.
This means the bound property doesn't get updated (and validated) unless the user pauses in typing for a set period of times.
The code can be found here (may need a bit of cleanup), and it is used like this:
<TextBox
local:DelayedUpdateBehavior.TargetProperty="{x:Static TextBox.TextProperty}"
local:DelayedUpdateBehavior.Milliseconds="1000"
Text="{Binding MyTextProperty, UpdateSourceTrigger=Explicit}" />
Edit: Actually this link might be better. It's a markup extension so you can use it directly from your binding. I can't remember which of these two methods I used in the past, but I know it was one of them :)
<TextBox Text="{local:DelayBinding Path=MyTextProperty, Delay='00:00:01'}" />
Assuming you're using an ICommand type interface for the button click event:
You can...Implement string properties with INotifyPropertyChanged and bind them to your textbox controls. Now in your Command canexecute method you can check to see if the property is !nullorempty.
e/ grammar
Set your Binding's UpdateSourceTrigger property to PropertyChanged. The default for TextBoxes is LostFocus.
Update: So you want to have data binding working on your TextBox and only allow numbers? Have a look at this question: Create WPF TextBox that accepts only numbers
Or use a converter and bind the Save button's IsEnabled property to your TextBox (maybe using a MultiBinding if there's more than one), and use a converter which determines if the text is a valid number and returns true or false.

MVVM detect Validation.HasError in View Model

I'm using MVVM and have most of my validation done using IDataErrorInfo and my ViewModel has an IsValid property which checks the validity of each member that needs to be validated. However I have a couple of textboxes bound to ints that can't be null, so I'm using a ValidationRule to alert the user (with a more friendly message than the "value could not be converted" one) if they blank that field out as obviously the property setter never gets called so the IDataErrorInfo code isn't called.
The problem is that I have a Save button (which is a RelayCommand) which I want disabled if there is any validation error. So the CanExecute of that command checks the VM's IsValid property. But obviously if the user blanks my int field the IDataErrorInfo knows nothing about it and currently the button won't disabled. Is there a way that the ViewModel can detect that error?
I thought I'd found a solution here
http://wpfglue.wordpress.com/2009/12/03/forwarding-the-result-of-wpf-validation-in-mvvm/
but having translated it to C# I can't get it working (the Coerce callback is never called). I don't understand dependency properties and objects very well yet (very new to WPF) and this solution looks complicated to me.
The only thing I can think to do is to get rid of the validation rule and make a nullable int wrapper, put TargetNullValue='' in the binding and then I can check them for null in the IDataErrorInfo code. I would prefer not to do this if there's a better way.
why not use string properties instead of int with IDataErrorInfo validation in your viewmodel? in your savecommand you can safely convert your string to your int values, if IDataErrorInfo has no errors of course. Using string properties with IDataErrorInfo is the most easy way.
edit: one more think, there is another problem if you not use string properties. say you have an int Property, and the user set a 10 in your textbox. so in your viewmodel you have the 10. now the user delete the 10 and set a abc in your textbox. your viewmodel still got the 10., because of the bindingconversationexception. thats why i almost use string properties. to be fair you can use behaviors for textbox to set a mask, so the user can not enter invalid data.
I can think of two strong options right away. One is to bind to a string property in your ViewModel, which in turn is programmed to only parse and store the underlying 'int' value if the string is determined to be valid. This ensures that your TextBox will always successfully store its databound value.
The second is to intercept the ValidationExceptions that occur in your View, storing them in your ViewModel via a custom Behavior. This article will essentially do exactly as you described in your question.
What you can try is BindingGroups and have a validation over the whole element, not just single properties. I used this for our modal dialogs to create a project for example, where certain settings must be set before finishing the dialog. This link explained it in good detail. This one is also quite detailed.

How can I add additional bindable visual state groups to a button?

I need to extend a button control to add some additional, bindable, visual states.
What I would like to create is an additional boolean property, to bind to, that will create a simple visual state change on the button. For this example, it could just be an additional border which changes colour according to the boolean value.
All the existing button behaviour should be entirely seperate from this new set of states.
Can this be done?
This can certainly be done. Here's a post that walks you through the steps you'll need to take, and includes additional information for extending the control with properties (besides just those to hold state) that show up in the final control. The pieces you'll need are:
A class that derives from Button (your custom control class)
A default style for this control (which goes in /themes/generic.xaml). You can start off with Button's generic style and add your states to it.
A dependency property that holds your boolean value
A new VisualStateGroup that holds your two new states
Some code in your class that glues together changing states with the boolean value you've defined, presumably resulting from user interaction, etc.
You may find it's easier to edit the visual state in Blend, depending on how sophisticated your transitions will be, etc.

Resources