在WPF绑定中获取IValueConverter实现的ConvertBack()方法中的Source值

时间:2011-08-15 11:34:05

标签: c# wpf binding ivalueconverter

我在WPF中将依赖属性绑定到textboxex。该属性是一个字符串,其中一些值以'/'分隔(例如:“1/2/3/4”)。我需要将单个值绑定到单独的文本框,这对于Convert()方法的以下实现很好:

public object Convert(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture)
{
  if (!string.IsNullOrEmpty(value as string))
  {
    String[] data = (value as string).Split('/');
    return data[Int16.Parse(parameter as string)];
  }
  return String.Empty;
}

我正在使用ConverterParameter中的xaml来指定所需值的位置。 但问题是使用ConvertBack()方法。我不知道,如何获取源值,这样我就可以在字符串中添加或更改一个值(在指定位置)。

感谢您的帮助。

5 个答案:

答案 0 :(得分:13)

<强>更新

你可能已经在 Vlad 的帮助下解决了你的问题,我只是想我应该添加另一种方法来实际获取转换器中的源值。

首先,您可以使转换器从DependencyObject派生,以便您可以向其添加依赖属性,我们将绑定到

public class MyConverter : DependencyObject, IValueConverter
{
    public static DependencyProperty SourceValueProperty =
        DependencyProperty.Register("SourceValue",
                                    typeof(string),
                                    typeof(MyConverter));
    public string SourceValue
    {
        get { return (string)GetValue(SourceValueProperty); }
        set { SetValue(SourceValueProperty, value); }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //...
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        object targetValue = value;
        object sourceValue = SourceValue;
        //...
    }
}

不幸的是,转换器没有DataContext所以Binding不会开箱即用,但你可以使用Josh Smith的优秀DataContextSpyArtificial Inheritance Contexts in WPF

<TextBox>
    <TextBox.Resources>
        <src:DataContextSpy x:Key="dataContextSpy" />
    </TextBox.Resources>
    <TextBox.Text>
        <Binding Path="YourProperty"
                 ConverterParameter="1">
            <Binding.Converter>
                <src:MyConverter SourceValue="{Binding Source={StaticResource dataContextSpy},
                                                       Path=DataContext.YourProperty}"/>
            </Binding.Converter>
        </Binding>
    </TextBox.Text>
</TextBox>

更新结束

Dr.WPF对此有一个优雅的解决方案,请参阅以下主题
The way to access binding source in ConvertBack()?

修改

使用Dr.WPF的解决方案,您可以使用此(可能有点详细)示例代码向转换器提供字符串索引和源TextBox

<TextBox dw:ObjectReference.Declaration="{dw:ObjectReference textBoxSource}">
    <TextBox.Text>
        <Binding Path="YourStringProperty"
                 Converter="{StaticResource YourConverter}">
            <Binding.ConverterParameter>
                <x:Array Type="sys:Object">
                    <sys:Int16>1</sys:Int16>
                    <dw:ObjectReference Key="textBoxSource"/>
                </x:Array>
            </Binding.ConverterParameter>
        </Binding>
    </TextBox.Text>
</TextBox>

然后您可以在以后访问ConvertBack方法中的索引和TextBox

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    object[] parameters = parameter as object[];
    short index = (short)parameters[0];
    object source = (parameters[1] as TextBox).DataContext;
    //...
}

答案 1 :(得分:5)

在大多数情况下,您可以安全地ConvertBack抛出NotImplementedException

实际上,您还没有足够的信息来重新创建源代码值!

如果你真的需要反向转换(例如,如果你使用双向绑定),我会将属性拆分为视图模型中的3个字符串(DataContext中使用的类),并绑定到它们分开。

答案 2 :(得分:1)

使用IMultiValueConverter和MultiBinding会不会更好?

public interface IMultiValueConverter
{
    object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);

    object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture);
}

答案 3 :(得分:1)

在这种情况下,如果你真的想要能够编辑成分, 您可以通过更复杂的对象来表示您的数字,该对象允许您通过索引器访问其4个组成部分。这样它只是一个简单的绑定和访问4个部分的对象,可以拼凑整个数字:

public class MyNumber {
  public int this[int index] {
    get { /**/ } set { /**/ }
  }
  public string FullNumber { get { /**/ } }
}

<TextBox Text={Binding MyNumber[0]}" />

答案 4 :(得分:0)

我刚刚建立了快速样本。请检查您是否正在寻找相同的。这在我的最后工作。

  • Xaml Code

    <StackPanel>
        <TextBox Text="1/2/3/4" x:Name="txtSource"></TextBox>
        <TextBox Text="{Binding ElementName=txtSource, 
                                Path=Text, 
                                Converter={StaticResource txtConv},
                                ConverterParameter='0'}" 
                 x:Name="txtTarget1"></TextBox>
        <TextBox Text="{Binding ElementName=txtSource, 
                                Path=Text, 
                                Converter={StaticResource txtConv},
                                ConverterParameter='1'}"
                 ></TextBox>
        <TextBox Text="{Binding ElementName=txtSource, 
                                Path=Text, 
                                Converter={StaticResource txtConv},
                                ConverterParameter='2'}" ></TextBox>
        <TextBox Text="{Binding ElementName=txtSource, 
                                Path=Text, 
                                Converter={StaticResource txtConv},
                                ConverterParameter='3'}"></TextBox>
    </StackPanel>
    
  • 背后的代码

    public class TextConverter : IValueConverter {
        #region IValueConverter Members
    
        public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            string input = (string)value;
            char[] sep = {'/'};
            string[] iparray = input.Split (sep);
            int index = Int32.Parse((string)parameter);
    
            return iparray[index];
        }
    
        public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            throw new NotImplementedException ();
        }
    
        #endregion
    }
    

但是,我无法理解ConvertBack方法的确切问题。你能详细说明一下吗?