WPF MultiBinding TextBlock.Text

wpf

The following code works to bind the the ListView, but any changes to the ListView are not going back to the in memory data structure. It works both ways when I had a standard binding, but not with a multibinding. I need to use a multibinding to get the StringFormat property used in the converter.

Could you please let me know a way to get the the 'ConvertBack' method of the converter called?

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:DataFlowControls">

    <local:ValueToFormatedValueConverter x:Key="valueToFormatedValueConverter" />

    <Style TargetType="{x:Type local:DfcEditTextBox}">
        <Setter Property="Margin" Value="-6, 0, -6, 0" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:DfcEditTextBox}">
                    <TextBlock x:Name="PART_TextBlock" Padding="2, 0, 0, 0">                               
                        <TextBlock.Text>
                            <MultiBinding Converter="{StaticResource valueToFormatedValueConverter}">   
                                <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
                                <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="StringFormat" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
                            </MultiBinding>
                        </TextBlock.Text>
                    </TextBlock>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>
<!--Text="{Binding Path=Value, Mode=TwoWay, Converter={StaticResource valueToFormatedValueConverter}, RelativeSource={RelativeSource TemplatedParent}}" />-->

<Window x:Class="DataFlowControls.Show.DfcListView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dfc="clr-namespace:DataFlowControls;assembly=DataFlowControls"
        xmlns:local="clr-namespace:DataFlowControls.Show"
        Title="DfcListView" Height="400" Width="500">
    <Grid>
        <StackPanel>
            <dfc:DfcListView Name="lvTradesCollection" ItemsSource="{Binding Path=TradesCollection}" KeyboardNavigation.DirectionalNavigation="Continue" >
                <ListView.ItemContainerStyle>
                    <Style TargetType="ListViewItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.Resources>
                    <DataTemplate x:Key="Date_DataTemplate">
                        <dfc:DfcEditTextBox Value="{Binding Path=Date, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" StringFormat='{}{0:dd/MM/yyyy}' HorizontalContentAlignment="Left" IsEditable="true" />
                    </DataTemplate>
                    <DataTemplate x:Key="Asset_DataTemplate">
                        <dfc:DfcEditTextBox Value="{Binding Path=Asset, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment="Left" IsEditable="true" />
                    </DataTemplate>
                    <DataTemplate x:Key="Lots_DataTemplate">
                        <dfc:DfcEditTextBox Value="{Binding Path=Lots, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" StringFormat='N0' HorizontalContentAlignment="Center" IsEditable="true" />
                    </DataTemplate>
                    <DataTemplate x:Key="Price_DataTemplate">
                        <dfc:DfcEditTextBox Value="{Binding Path=Price, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" StringFormat='N2' HorizontalContentAlignment="Center" IsEditable="true" />
                    </DataTemplate>
                    <DataTemplate x:Key="IsCheap_DataTemplate">
                        <dfc:DfcEditCheckBox Value="{Binding Path=IsCheap, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" IsEditable="true" />
                    </DataTemplate>
                    <DataTemplate x:Key="NextTrade_DataTemplate">
                        <dfc:DfcEditComboBox Value="{Binding Path=NextTrade, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{x:Static local:DfcListView.NextTradeTypes}" IsEditable="true" />
                    </DataTemplate>
                </ListView.Resources>
                <ListView.View>
                    <dfc:DfcGridView>
                        <dfc:DfcGridViewColumn Header="Date" Width="140" CellTemplate="{StaticResource Date_DataTemplate}" />
                        <dfc:DfcGridViewColumn Header="Asset" Width="40" CellTemplate="{StaticResource Asset_DataTemplate}" />
                        <dfc:DfcGridViewColumn Header="Lots" Width="40" CellTemplate="{StaticResource Lots_DataTemplate}" />
                        <dfc:DfcGridViewColumn Header="Price" Width="50" CellTemplate="{StaticResource Price_DataTemplate}" />
                        <dfc:DfcGridViewColumn Header="IsCheap" Width="60" CellTemplate="{StaticResource IsCheap_DataTemplate}" />
                        <dfc:DfcGridViewColumn Header="NextTrade" Width="80" CellTemplate="{StaticResource NextTrade_DataTemplate}" />                                                                         
                    </dfc:DfcGridView>
                </ListView.View>
            </dfc:DfcListView>
            <Button Content="Add Row" HorizontalAlignment="Left" Margin="5,5,5,5" Click="AddRow_Click"/>
            <Button Content="Update Row" HorizontalAlignment="Left" Margin="5,5,5,5" Click="UpdateRow_Click"/>
        </StackPanel>
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Globalization;
using System.Windows;

namespace DataFlowControls
{
    public class ValueToFormatedValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            object valueObject = values[0];
            string stringFormat = (string)values[1];

            if (stringFormat == null)
            {
                return valueObject.ToString();
            }
            if (stringFormat.Substring(0, 1) == "N")
            {
                int intValue;
                if (Int32.TryParse(valueObject.ToString(), out intValue))
                {
                    return (intValue * 100).ToString(stringFormat);
                }
                double doubleValue;
                if (Double.TryParse(valueObject.ToString(), out doubleValue))
                {
                    return doubleValue.ToString(stringFormat);
                }
                decimal decimalValue;
                if (Decimal.TryParse(valueObject.ToString(), out decimalValue))
                {
                    return decimalValue.ToString(stringFormat);
                }
            }
            if (stringFormat == "{0:dd/MM/yyyy}")
            {
                return ((DateTime)valueObject).ToShortDateString();
            }
            throw new NotImplementedException();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            return Enumerable.Repeat(value, targetTypes.Length).ToArray();
        }      
    }
}

Best Answer

You need to set TwoWay mode on MultiBinding explicitly:

<TextBlock.Text> 
    <MultiBinding Converter="{StaticResource valueToFormatedValueConverter}"
                  Mode="TwoWay">    
        <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/> 
        <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="StringFormat" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/> 
    </MultiBinding> 
</TextBlock.Text>
Related Topic