Получите значение Source в методе ConvertBack () для реализации IValueConverter в привязке WPF - PullRequest
7 голосов
/ 15 августа 2011

Я связываю свойство зависимости с textboxex в WPF.Свойство представляет собой строку, в которой некоторые значения разделены символом «/» (пример: «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 ]

13 голосов
/ 15 августа 2011

Обновление

Вы, вероятно, уже решили свою проблему с помощью Влад , я просто подумал, что должен добавить еще один способ фактического получения значения источника в конвертере.

Сначала вы можете сделать свой конвертер производным от 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, поэтому привязка не будет работать из коробки, но вы можете использовать превосходный DataContextSpy: Контекст искусственного наследования в 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 предлагает элегантное решение, см. Следующую ветку
Как получить доступ к источнику привязки в 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>

И затем вы можете получить доступ как к индексу, так и к TextBox в методе ConvertBack

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;
    //...
}
5 голосов
/ 15 августа 2011

В большинстве случаев вы можете спокойно сделать ConvertBack просто бросить NotImplementedException.

Действительно, у вас просто недостаточно информации, чтобы воссоздать исходное значение из его части!

Если вам действительно нужно обратное преобразование (например, если вы используете привязку в двух направлениях), я бы разделил свойство на 3 строки в модели представления (класс, используемый в DataContext) и привязал бы их отдельно.

1 голос
/ 15 августа 2011

В этом случае, если вы действительно хотите иметь возможность редактировать составляющие, Вы можете представить свой номер более сложным объектом, который позволяет вам получить доступ к его 4 составным частям через индексатор. Таким образом, это просто простая привязка, и объект, который содержит 4 части, доступен и может собрать воедино целое число:

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

<TextBox Text={Binding MyNumber[0]}" />
1 голос
/ 15 августа 2011

Будет ли лучше использовать 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);
}
0 голосов
/ 16 августа 2011

Я только что создал быстрый образец.Пожалуйста, проверьте, если вы ищете то же самое.Это работает на моем конце.

  • Код 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.Не могли бы вы уточнить это?

...