【问题标题】:Get the Source value in ConvertBack() method for IValueConverter implementation in WPF binding获取 WPF 绑定中 IValueConverter 实现的 ConvertBack() 方法中的 Source 值
【发布时间】:2011-10-27 05:24:37
【问题描述】:

我在 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;
}

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

感谢您的帮助。

【问题讨论】:

  • 你能把属性改为 IList 吗?
  • 我正在使用 LINQ to SQL 类,我可能需要更改生成的代码

标签: c# wpf binding ivalueconverter


【解决方案1】:

更新

您可能已经在 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,因此绑定无法开箱即用,但您可以使用 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;
    //...
}

【讨论】:

  • 好的,谢谢,但我已经在使用 Dr.WPF 用来保存对象的ConverterParameter
  • @tom: 如果你使用 &lt;x:Array "sys:Object"&gt;..,你可以为 ConverterParameter 提供多个值
  • 我不知道我是否理解正确,但TextBox.Textobject value 所持有的。我需要从绑定的依赖属性中获取原始值(在使用Convert()方法转换并由TextBox显示之前)
  • @tom:你说得对,对不起,我搞混了。您应该改为访问DataContext
  • 通过Dr.WPF instructions我也意识到,我可能不需要那个扩展,因为我想得到一个DependencyProperty的值所以我不能以某种方式传递它ConvertParameter 按照您的建议使用 x:Array
【解决方案2】:

我刚刚建立了快速样本。请检查您是否正在寻找相同的内容。这对我有用。

  • Xaml 代码

    <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 方法的确切问题。能否请您详细说明一下?

【讨论】:

  • 我实际上是绑定到在实现 INofifyPropertyChanged 接口的代码中创建的属性,并在将 LINQ 添加到 SQL 类时由向导生成。问题是实现 ConvertBack 方法,但我已经标记了我使用的答案(来自 Vlad)
【解决方案3】:

在这种情况下,如果您真的希望能够编辑成分, 你可以用一个更复杂的对象来表示你的号码,它允许你通过索引器访问它的 4 个组成部分。这样,它只是一个简单的绑定,并且可以访问保留 4 个部分的对象,并且可以将整数拼凑在一起:

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

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

【讨论】:

    【解决方案4】:

    使用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);
    }
    

    【讨论】:

    【解决方案5】:

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

    确实,您只是没有足够的信息来重新创建源值!

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

    【讨论】:

    • 它不应该抛出一个NotImplementedException,而是一个NotSupportedException,因为该方法永远不会被实现。
    • 我确实需要实现该方法,因为我使用的是TwoWay绑定模式
    • @tom: 那么你应该用四个替换你的依赖属性,每个代表字符串的一部分。
    • @Vlad:嗯,在 VS2010 中通过向导将 LINQ 添加到 SQL 类时会自动生成该属性。它与数据库中的一列相关联,该列包含诸如“1/2/3/4”之类的值。最重要的是,我需要绑定大约 10 列这种形式
    • @tom:你可以使用一个提供四个属性的中间类,像这样:pastebin.com/cLWAbLaC
    猜你喜欢
    • 1970-01-01
    • 2016-05-29
    • 2011-01-15
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 2010-09-15
    • 2011-02-02
    • 1970-01-01
    相关资源
    最近更新 更多