Is it possible in WPF to bind to 2 elements?
For example I'd like to display something like myserver.com:80 in a textbox.
So to do this I'd like to bind to both a Host field then add a ":" then bind to a port field in my object all for the same label content.
In WPF 4/3.5SP1 you can use a MultiBinding in conjunction with StringFormat:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{0}:{1}">
<Binding Path="Host"/>
<Binding Path="Port"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Prior to WPF 4 you can still use a MultiBinding but would need to write your own converter instead.
An alternative to both these approaches is do MVVM and expose a property that does the concatenation for the view, then the view just binds directly to that property.
Related
I have created an AttachedProperty that has a PropertyChangedCallback function, which does some formatting to a TextBlock. But to perform the formatting, the Tag attribute is needed. The Tag itself is bound to the output of a Multiconverter.
But my problem is, that the FNamePropertChangedCallback is executed before the Tag is bound to the output of the Multibinding. Thus Tag still Null, when FNamePropertyChangedCallback is triggered.
Is there any way to influence the order in which the Attributes are bound?
I need to bind Tag before binding FInlineProperty.
public static readonly DependencyProperty FInlinePropertyProperty =
DependencyProperty.RegisterAttached("FInlineProperty", typeof(string), typeof(MainWindow),
new PropertyMetadata(null, FNamePropertyChangedCallback));
<TextBlock local:MainWindow.FInlineProperty="{Binding Name}" TextWrapping="WrapWithOverflow">
<TextBlock.Tag>
<MultiBinding Converter="{StaticResource TupleConverter}">
<Binding />
<Binding ElementName="Window"/>
</MultiBinding>
</TextBlock.Tag>
</TextBlock>
Btw: Does someone know how to write local:MainWindow.FInlineProperty="{Binding Name}" in long form? I tried <TextBlock.local:MainWindow.FInlinse>...</TextBlock.local:MainWindow.FInlinse>, but the compiler complains about it.
Update 25.Feb.2017:
I did what you suggested and bound everything to my Attached Property.
<TextBlock TextWrapping="WrapWithOverflow" >
<local:MainWindow.FInlineProperty>
<MultiBinding Converter="{StaticResource GroupConverter}">
<Binding />
<Binding ElementName="Window" Path="MySetup" />
</MultiBinding>
</local:MainWindow.FInlineProperty>
</TextBlock>
The problem with this is, that it is working the first time when the ListBoxItem is created. But updating properties from MySetup does not re-trigger FNamePropertyChangedCallback.
MySetup.ColorString = "green"; // this does not retrigger the callback
MySetup = MySetup.Copy(); // this does retrigger the callback
So currently only assigning MySetup a new copy of itself (changing the reference) triggers callback function again.
That was the reason, why I bound the name property explicitly.
MySetup.ColorString would trigger, if I bind to it explicitly, but I need to bind to MySetup to have all data, so the question is, how to force the binding to execute again, when the bound object itself (reference) has not changed, but something inside did change?
What you actually want is binding between your AttachedProperty and TextBlock.Tag property, so that AttachedProperty is set when Tag changes. But since you are also binding to Name, so I suggest to use MultiBinding for your AP using Name and Tag bindings, thus not depending upon Tag at all.
Try to set the Tag property before you set the attached property. This means that you should also set the attached property using element syntax:
<TextBlock TextWrapping="WrapWithOverflow">
<TextBlock.Tag>
<MultiBinding Converter="{StaticResource TupleConverter}">
<Binding />
<Binding ElementName="Window"/>
</MultiBinding>
</TextBlock.Tag>
<local:MainWindow.FInlineProperty>
<Binding Path="Name" />
</local:MainWindow.FInlineProperty>
</TextBlock>
I have a TextBlock with two MultiBindings. I'd like to make a user control out of this, as I need several instances. The only difference amongst the instances is the Name, and that is only needed as a sort of parameter to the MultiBinding.
<TextBlock x:Name="That"><
TextBlock.Foreground>
<MultiBinding Converter="{StaticResource multiValueFgColorConverter}">
<Binding ElementName="That" Path="Name" />
<Binding Path="TimerState" Mode="TwoWay" />
<Binding Path="Which" Mode="TwoWay" />
</MultiBinding>
</TextBlock.Foreground><TextBlock.Opacity>
<MultiBinding Converter="{StaticResource multiValueOpacityConverter}">
<Binding ElementName="That" Path="Name" />
<Binding Path="TimerState" Mode="TwoWay" />
<Binding Path="Which" Mode="TwoWay" />
</MultiBinding>
</TextBlock.Opacity><Bold><Run Text="That"/></Bold>
-- Is there a way to inject the Name in to an instance of the user control?
-- Or, perhaps wrap this user control in another control where it is used, and have the UC inherit the parent's name?
<grid x:Name="That">
<my:UC/> <!-- 'Inherits' "That"? -->
</grid>
-- Alternatively, is there a way to pass a string as a parameter to the MultiBinding? MultiBinding doesn't take ConverterParameters, as far as I know, so it has to be fudged through the Binding (although I am probably unaware of the better way...)
Thanks for any insights --
Within UserControl expose dependency property and within MultiBinding bind to it. Every single instance of UserControl can then assign binding to specific property making multiBinding updated.
As far as inheriting is concerned, you can inherit propertie's value as long as it allows to do so. x:Name is not able to be inherited.
It's been a while since I touched WPF, can't you use Relative source for that ?
See below.
How do I use WPF bindings with RelativeSource?
So the issue is that when I normally bind a single text item to the Text in a TextBlock, the syntax is as follows:
<TextBlock ... Text="{Binding Attributes[StatusDateTime]}" /> //WORKS GREAT!
Now, background is that the DataContext for this part of the app is the output of a 3rd party API. "Attributes" is a collection of KeyValuePair, which is a property of the parent object. StatusDateTime is the key for the value I am returning. The syntax above works just great! So the object would look something like: theDataContextObject.Attributes[StatusDateTime].
BUT, if I need to combine multiple attributes into one TextBlock that's when things get hairy. I have no idea how to access the key from an actual Binding tag:
<TextBlock Grid.Row="0" Grid.ColumnSpan="3" Style="{StaticResource popupText}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} at {1}">
<Binding Path="{Attributes[Type]}"/>
<!--<Binding Path="StatusDateTime" />-->
<Binding Path=Attributes[Type]/>
<Binding Path="Type" ElementName="Attributes"/> //the element has no
//name it's just the datacontext
<Binding Path="[StatusDateTime]" />
<Binding Path="Attributes[StatusDateTime]"/>
</MultiBinding>
</TextBlock.Text>
I know the number of examples above does not match the stringformat, I was just pasting examples of my guesses into the multibinding of how to get these values bound.
Apologies if this is a duplicate with another question. I am not sure what to even call this kind of binding where I'm just passing Attributes[StatusDateTime] directly to binding. Keep in mind that Attributes is not the name of an object, it's a property of the object passed to datacontext of the TextBlock's parent control.
So how do I bind to the value of key in the KeyValuePair collection when i have to use a Binding tag inside a MultiBinding?
I have 2 string variables var1,var 2 .I need to show
For information on returns and exchanges please visit {var 1} or call {var2}.
any xaml solution available for that?.
You can use a MultiBinding, like this:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="For information on returns and exchanges please visit {0} or call {1}.">
<Binding Path="SomeProperty"/>
<Binding Path="SomeOtherProperty"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Note that the SomeProperty and SomeOtherProperty are simple bindings to the DataContext of the TextBlock, such as the View Model or underlying Model.
I'm making a WPF application and I need a value convertor with more than 1 binding path, is that possible?
It works with 1 path so far:
Binding="{Binding Path=Price, Converter={StaticResource vPriceConvertor}}"
I wanna give the Price and the discount to the converter so he can calculate the endprice.
Value converters are intended... for value conversion. That's why they're value converters.
To do what you want, you should make a property EndPrice in view model, and calculate its value in view model. Why are you trying to bring a non-UI logic into UI??
Look at the MultiBinding class. For example:
<TextBlock Name="textBlock" DataContext="{StaticResource myViewModel}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource vPriceConvertor}"
ConverterParameter="myParameter">
<Binding Path="Price"/>
<Binding Path="Discount"/>
<!-- Insert other paths here -->
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Implement IMultiValueConverter instead of IValueConverter to actually do the conversion, since it supports multiple sources.
Parys -
You could always create a collection (in View Model) which contains Price and Discount and then pass it through your XAML (through IValueConverter).
But to re-iterate #Dennis and everybody else point - then your converter will have calculation logic - which is not recommended.