How to supply a string literal value as a binding in WPF - wpf

EDIT:
My former question also referred to commands, but as pointed out in a comment below, it was unnecessary and added noise.
This is more a XAML syntax question, so it is probably trivial.
I would like to know how to pass a string literal as a value for a binding in WPF.
If the value is already known from the context in XAML, may its value simply be directly assigned to the binding, instead of using paths and other means?
If so, what would the syntax be in that case?
<MultiBinding.Bindings>
<!-- First binding, a textbox -->
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TextBox}}"/>
<!-- Second binding, I want to pass a string as is, for instance, "Description" -->
<!-- The proper syntax for the line below is what I am after -->
<Binding Value="Description"/>
</MultiBinding.Bindings>

It's
<Binding Source="Description"/>
Source can be any type, so in attribute syntax that is interpreted as a string, if no Path is specified a binding's value is the source.
Also that is a multi-binding, i would not talk about command parameters as that is irrelevant to the matter...

Related

Extending Binding class to provide a bindable converter parameter

I need to create a string in a particular format, for which I use IMultiValueConverter. Example:
{0} of {1} in {2}
SomeValue0
SomeValue1
SomeValue2
Results in:
SomeValue0 of SomeValue1 in SomeValue2
This part is not a problem. Basically converter accepts multiple strings, of which the first one is the string format, and later ones are the strings to format.
<MultiBinding Converter={...}>
<Binding>
<Binding.Source>{0} of {1} in {2}</Binding.Source>
</Binding>
<Binding Path="Value0" />
<Binding Path="Value1" />
<Binding Path="Value2" />
</MultiBinding>
It gets tricky when some of the strings (Binding) also require the use of IMultiValue converter. Imagine that property #Value1# has different value for different language. Normally we get such value also using IMultiValueConverter:
<TextBox>
<TextBox.Text>
<MultiBinding Converter={...}>
<Binding Path="Value1"?
<Binding Path="Strings" Source="{StaticResource langResources}" />
</MultiBinding>
</TextBox.Text>
</TextBox>
When the user switches to different language, a dictionary of Strings is updated, and TextBox receives new value (the same applies to changing a value to Value1).
Now the problem: It is not possible to use IMultiValueConverter inside IMultiValueConverter. You also cannot override ProvideValue for BindingBase, and IMultiValueConverter will accept only the objects of type BindingBase.
Is there any way I can somehow extend BindingBase so that it exposes a BindableConverterProperty, whose value will be used to provide value from Binding?
tricky when some of the strings (Binding) also require the use of IMultiValue converter.
Why not put the intelligence of the string's IMultivalue converter into a specialized class who's ToString() will output the correct string based on the current environmental settings? That would eliminate the need for the sub multivalue converter you describe but work within the framework of the parent MultiValue converter.
The super-classed string class I recommend simply has to subscribe to an event which informs it which dictionary to use. Then when ToString() is called, the correct string is passed on to the top level converter.

Do you have to use a converter when using Multibinding in WPF?

I would like to know if there are scenarios where you can use a Multibinding without a converter - and the limitations which force us to use a converter.
In particular I am trying to bind a string to another two strings in a string.format style.
The most common area you use a MultiBinding without a converter is when you have a string format concatenating two individual values
say for example:
To format Names that have First, Last part and you want to format it based on locale
<StackPanel>
<TextBlock x:Name="firstName"
Text="John" />
<TextBlock x:Name="lastName"
Text="Wayne" />
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding ElementName="firstName"
Path="Text" />
<Binding ElementName="lastName"
Path="Text" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
You do see quite a lot of places you use a converter since using a MultiBinding your doing the same as a Binding but you have multiple source values formatted to a single result instead of single input -> single output.
You can have a Binding take a ConverterParameter to supply another input value however you have limitations like not being able to provide a runtime Bound value to it, which makes MultiBinding more appropriate for multiple inputs where you want to bind all of them.
It boils down to your use-case, If you want to provide a result based on different input types that you evaluate in a custom-way, you need a Converter(pretty much similar to Binding. Just think of the difference as 1 input bind-able value against multiple)

MultiBinding not working but corresponding Binding does work

I have the following code:
<local:StaffAtMeetingEditor DataContext="{Binding Meeting}" Grid.Row="1">
<local:StaffAtMeetingEditor.InEditMode>
<MultiBinding Converter="{StaticResource myMeetingLogEditableMultiConverter}">
<Binding Path="ParentSI.ItemInEditMode"/>
</MultiBinding>
</local:StaffAtMeetingEditor.InEditMode>
</local:StaffAtMeetingEditor>
The setup is that the containing control's datatype is "SIP_ServiceItem". This class has a property called "Meeting" (which is set as the DataContext for the local:StaffAtMeetingEditor control), which itself has a member called "ParentSI", pointing back to the parent SIP_ServiceItem object.
The issue is, that if I pass this through as a single binding (i.e. remove the start and end MultiBinding tags from the code above, leaving just the Binding), it works just fine. But when I make it a MultiBinding (I wish to add some other Bindings to this shortly), and try to pass the bound value through to myMeetingLogEditableMultiConverter, the values(0) parameter, which should correspond to the boolean ParentSI.ItemInEditMode is actually an MS.Internal.NamedObject, implying there's a null reference somewhere. Furthermore, the ParentSI property is never being evaluated, so something is going completely wrong. I am at a loss to know the difference between the single binding and multi binding cases.
Thanks.
I know this is a bit old, and you have likely figured this out by now, but I came across this as I had a similar problem and thought I'd share the solution: I had the same problem and have added the attributes ElementName and Mode as below:
<Binding Path="CurrentProvider.IsBusy" ElementName="parent" Mode="OneWay" />
Hope this helps someone, even if the OP has fixed their issue.
May be you should try to add any temporary unused bound value. For instance:
<local:StaffAtMeetingEditor DataContext="{Binding Meeting}" Grid.Row="1">
<local:StaffAtMeetingEditor.InEditMode>
<MultiBinding Converter="{StaticResource myMeetingLogEditableMultiConverter}">
<Binding Path="ParentSI.ItemInEditMode"/>
<Binding Path="ParentSI"/>
</MultiBinding>
</local:StaffAtMeetingEditor.InEditMode>
</local:StaffAtMeetingEditor>
If it doesn't work then your implementation is wrong, another case - it's MultiBinding limitations.

Can a WPF converter access the control to which it is bound?

Long version:
I have a simple WPF converter than does date conversions for me. The converter basically checks the date and formats it in dd/M/yyyy format. The converter does some smarts with the handling of the date which means that the user could type "23061971" and the value will be converted to "23/06/1971".
All this is trivial and working. The problem is that when I update the value, it does not update the caret position. Assume "|" is the caret and the user types "23061971|" then a millisecond later it is updated to "230619|71".
What I'd like to do is detect if the caret at the end of the value - if so, shift it to the end of the edit field once the new value has been updated. In order to do this, I'll need access to the edit control to which the converter is attached.
Short version:
From A WPF converter, can I get a reference to the control that is bound to that converter?
Here is an excellent article on how to get direct access to the control from within a converter: http://social.technet.microsoft.com/wiki/contents/articles/12423.wpfhowto-pass-and-use-a-control-in-it-s-own-valueconverter-for-convertconvertback.aspx
Essentially:
<MultiBinding Converter="{StaticResource MyConverter}" >
<Binding RelativeSource="{RelativeSource Self}" Mode="OneTime"/>
<Binding Path="MyValue2" />
</MultiBinding>
in the converter values[0] will be your control, ready for casting and values[1] would be the data that you are binding.
In a ValueConverter you can't get access to the control - however you can get access if you use a multibinding with a multivalueconverter.
In the multibinding the first binding is your binding as now - without the converter. The second binding you bind to the control itself - there you go acces to the control.
I have used this approach to gain other things also - you can make "dummy" bindings to properties you want to trigger updates, i.e. if you bind to the control itself you will only get updated if it changes, not if a property does - so create dummybindings for those.
You can send the control with the MultiBinding like this.
<TextBox Height="100" x:Name="textbox1" DockPanel.Dock="Top">
<TextBox.Text>
<MultiBinding Converter="{StaticResource MultiConverter}">
<Binding ElementName="textbox1" Path="." />
</MultiBinding>
</TextBox.Text>
</TextBox>
I don't thknk a converter has any way to get at the control that is using it. It is only a simple piece of logic that converts one object to another object.
However, in you case, perhaps you can trap the change event and then manually move the caret. If you think about it, caret position is strictly a view concern; it has nothing to do with converters or the data. You should not burden view-controller logic with it. You should definitely not burden converter logic (which is classified under utility classes) with it.

Why does my IMultiBindingConverter get an array of strings when used to set TextBox.Text?

I'm trying to use a MultiBinding with a converter where the child elements also have a converter.
The XAML looks like so:
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource localizedMessageConverter}" ConverterParameter="{x:Static res:Resources.RecordsFound}" >
<Binding Converter="{StaticResource localizedMessageParameterConverter}" ConverterParameter="ALIAS" Path="Alias" Mode="OneWay" />
<Binding Converter="{StaticResource localizedMessageParameterConverter}" ConverterParameter="COUNT" Path="Count" Mode="OneWay" />
</MultiBinding>
</TextBlock.Text>
The problem I'm facing here is, whenever this is used with a TextBlock to specify the Text property, my IMultiValueConverter implementation gets an object collection of strings instead of the class returned by the IValueConverter. It seems that the ToString() method is called on the result of the inner converter and passed to the IMultiValueConverter. If used to specify the Content property of Label, all is well.
It seems to me that the framework is assuming that the return type will be string, but why? I can see this for the MultiBinding since it should yield a result that is compatible with TextBlock.Text, but why would this also be the case for the Bindings inside a MultiBinding?
If I remove the converter from the inner Binding elements, the native types are returned. In my case string and int.
Probably the targetType parameter of your localizedMessageParameterConverter converter is System.String. This is because the target type of the Bindings is inherited from the MultiBinding, and the targetType of the MultiBinding is System.String because TextBlock.Text is a string property.
See the following article for a similar problem: Multi-Value Converters, Value Converters and the Case of the Wrong Target Type
According to Microsoft Connect, this has been fixed in WPF 4.0. See: Microsoft Connect
The above article also explains a workaround.

Resources