WPF Value Converter - c#

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.

Related

WPF Binding inside Text attribute differs from actual Binding tag syntax in MultiBinding

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?

Customizing a Listbox - How to pass a Listbox Reference to a Converter from within an ItemTemplate?

I have a list of objects with properties Name and Value which are shown in a listbox. The list is ordered by Name and i need to show the sum of the values of all preceeding objects in a third column of my Listbox.
I created an ItemTemplate from where i call a ListItemConverter which is supposed to convert any ListItem into the required double value by accessing the parent Listbox. I can pass the current ListItem (or rather the according ContentPresenter) to my converter as
RelativeSource="{RelativeSource TemplatedParent}"
However the ListItem does not contain the information of the whole Listbox (which seems quite obvious when i state it this way), so i need to pass a reference to my Listbox (or the list which i use as ItemSource) to the Converter as well.
How do i pass a second parameter to my converter and how can i access the parent Listbox as a Resource from within my ItemTemplate?
you have two options:
Create third property in your item class, or create new Item class with Name, Value and Sum properties. Use this especially in mvvm scenarios
Use MultiConverter and MultiBinding:
<ListBox ItemsSource="{Binding MyCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource YourMultiConverter}">
<Binding />
<Binding Path="ItemsSource" RelativeSource="{RelativeSource AncestorType=ListBox}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Apply value converter in XAML without databinding

I have a TextBlock in my view that I want to always display the number 1, converted into the local currency. (e.g. $1 in US, £1 in UK, etc). I have a value converter that can do this, but I don't know how to apply a value converter to the value of 1 without getting my data from a databinding.
I can think of two solutions, but they each have their problems, and I'm looking for something more elegant:
Create a property on my ViewModel that just holds and returns the value 1 and bind to it. Then add my converter to this binding. This seems backwards, particularly as this is view-only code.
Make a binding point to an existing property and modify my converter to ignore the value given to it, and instead use the parameter to give it the number 1. This feels unintuitive to other programmers, as they'll be confused as to why I'm binding to a different property there.
Is there some way of applying a converter without first creating a binding?
If you want for this to be relatively readable from XAML alone, you can always do it like this:
<Label>
<Label.Resources>
<system:Int32 x:Key="defaultValue">1</system:Int32>
</Label.Resources>
<Label.Content>
<Binding Source="{StaticResource defaultValue}"
Converter="{StaticResource CurrencyConverter}" />
</Label.Content>
</Label>
I had similar situation, I needed to convert static enum value placed directly in xaml to be converted by my custom converter without using databinding.
<Border>
<Border.Background>
<Binding Source="{x:Static enumeration:ColorType.Main}"
Converter="{StaticResource ColorConverter}" />
</Border.Background>
</Border>

WPF Multibinding to View Model

I am trying to multibind a formatted double value to a text box. I have a converter which takes in a double and a Formatter object and returns a formatted string to be displayed. The double is bound to a particular data source and the formatter is a property in the view model. The problem I'm having is that I'm unable to bind to the view model property. This is my code in xaml
<StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock HorizontalAlignment="Left" Style="{StaticResource HintDataItemsStyle}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource FormatConverter}">
<Binding Path="OpenValue" />
<Binding Path="XLabelFormatterY1" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
This is the property in the view model
private ILabelFormatter _labelFormatterY1;
public ILabelFormatter XLabelFormatterY1
{
get { return _labelFormatterY1; }
set
{
_labelFormatterY1 = value;
OnPropertyChanged("XLabelFormatterY1");
}
}
So, in my converter I'm able to pick up the value for "OpenValue" ,but the runtime is unable to find XLabelFormatterY1. Most of the examples I have seen for multibinding bind to gui components. I'm trying to bind to the view model and would appreciate all help.
Old question but without answer. I beleive that you are looking for this solution. If this answer doesn't work for you, try to explicitly set NotifyOnSourceUpdated="True" in the binding. And also double check if you have set correct AncestorType as wookietomwookie says in his answer.

Binding to 2 string elements?

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.

Categories

Resources