Гость
Map
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Динамически переназначить свойство TextBox / 9 сообщений из 9, страница 1 из 1
01.02.2021, 13:54
    #40040482
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
Добрый день!

Подскажите пожалуйста как при помощи триггера, можно проделать тоже самое, но с TextBox?

В примере указан TextBlock
https://overcoder.net/q/632248/условное-связывание-текста-xaml
...
Рейтинг: 0 / 0
01.02.2021, 16:15
    #40040562
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
у <TextBlock> есть свойство Inlines
В котором можно описать TextBlock более сложно, нужно учитывать, что это Freezable объект и вроде он замораживается, но это не точно.
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
<StackPanel>
	<CheckBox x:Name="Visibily1" Content="Text 1 Visibility" IsChecked="True" />
	<CheckBox x:Name="Visibily2" Content="Text 2 Visibility" IsChecked="True"/>
	<TextBlock>
		<TextBlock.Inlines>
			<local:VisibilitySpan IsVisible="{Binding IsChecked, ElementName=Visibily1}">
				<Run Text="{Binding Text1}" />
			</local:VisibilitySpan>
			<local:VisibilitySpan IsVisible="{Binding IsChecked, ElementName=Visibily2}">
				<Run Text="{Binding Text2}" />
			</local:VisibilitySpan>
		</TextBlock.Inlines>
	</TextBlock>
</StackPanel>


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
public class VisibilitySpan : Span
{
	private Inline oldInline;

	public bool IsVisible
	{
		get => (bool)GetValue(IsVisibleProperty); 
		set => SetValue(IsVisibleProperty, value);
	}
	public static readonly DependencyProperty IsVisibleProperty =
		DependencyProperty.Register(nameof(IsVisible), typeof(bool), typeof(VisibilitySpan), new PropertyMetadata(true, OnPropertyChanged));

	private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
	{
		((VisibilitySpan)d).UpdateVisibility((bool)e.NewValue);
	}

	private void UpdateVisibility(bool value)
	{
		if (value)
		{
			if (oldInline != null)
			{
				AddLogicalChild(oldInline);
			}
		}
		else
		{
			if (Inlines.Count > 1) throw new NotSupportedException();
			oldInline = Inlines.FirstInline;
			if (oldInline != null)
			{
				RemoveLogicalChild(oldInline);
			}
		}
	}
}
...
Рейтинг: 0 / 0
01.02.2021, 17:06
    #40040592
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
Ну это с использованием TextBlock.

А можно как проделать подмену с textbox? Мне нужно чтобы поле можно было редактировать

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<TextBox>
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Setter Property="Text" Value="{Binding Value0}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IndexParam}" Value="1">
                    <Setter Property="Text" Value="{Binding Value1}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding IndexParam}" Value="2">
                    <Setter Property="Text" Value="{Binding Value2}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>



Код: c#
1.
2.
3.
4.
5.
public class Test {
public int Value0 {get;set;}
public int Value1 {get;set;}
public int Value2 {get;set;}
}



В зависимости от выбранного параметра IndexParam, изменялось нужное значение, через один TextBox
...
Рейтинг: 0 / 0
01.02.2021, 19:21
    #40040654
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
RichTextBox работает на том же FlowDocument, разные поля можно поместить под разные спаны с форматированием, и немного разобраться с позиционированием
как вариант можно делать несколько текстбоксов в 1 контроле
...
Рейтинг: 0 / 0
02.02.2021, 08:23
    #40040774
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
Nechto,

вариантов здесь больше 1.
Самый простой - 2 текстбокса, привязанные соответственно к Value1 и Value2, и скрываемые/отображаемые в зависимости от IndexParam:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
public class TestModel: INotifyPropertyChanged
{
  string _value1;
  public string Value1
  {
    get => _value1;
    set
    {
      _value1=value;
      OnPropertyChanged();
    }
  }

  string _value2;
  public string Value2
  {
    get => _value2;
    set
    {
      _value2=value;
      OnPropertyChanged();
    }
  }

  int _indexParam=1;
  public int IndexParam
  {
    get => _indexParam;
    set
    {
      if (value!=1 && value!=2)
        throw new ArgumentException();
      _indexParam=value;
      OnPropertyChanged();
      OnPropertyChanged(nameof(Value1));
      OnPropertyChanged(nameof(Value2));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
<Window.Resources>
  <local:TestModel x:Key="TestModel" />
  <local:BoolToIntConverter x:Key="BoolToIntConverter" />
  <system:Int32 x:Key="KeyOne">1</system:Int32>
  <system:Int32 x:Key="KeyTwo">2</system:Int32>
</Window.Resources>

<Window.DataContext>
  <StaticResource ResourceKey="TestModel" />
</Window.DataContext>

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <CheckBox
    VerticalAlignment="Center"
    HorizontalAlignment="Center"
    IsChecked="{Binding IndexParam,
      Converter={StaticResource BoolToIntConverter},
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged}">
    <CheckBox.Style>
      <Style TargetType="{x:Type CheckBox}">
        <Setter Property="Content" Value="Changing Value1" />
        <Style.Triggers>
          <Trigger Property="IsChecked" Value="True">
            <Setter Property="Content" Value="Changing Value2" />
          </Trigger>
        </Style.Triggers>
      </Style>
    </CheckBox.Style>
  </CheckBox>
  <Grid
    Grid.Row="1"
    VerticalAlignment="Center">
    <TextBox Text="{Binding Value1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
      <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
          <Style.Triggers>
            <DataTrigger Binding="{Binding IndexParam}" Value="{StaticResource KeyTwo}">
              <Setter Property="Visibility" Value="Collapsed" />
            </DataTrigger>
          </Style.Triggers>
        </Style>
      </TextBox.Style>
    </TextBox>
    <TextBox Text="{Binding Value2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
      <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
          <Setter Property="Visibility" Value="Collapsed" />
          <Style.Triggers>
            <DataTrigger Binding="{Binding IndexParam}" Value="{StaticResource KeyTwo}">
              <Setter Property="Visibility" Value="Visible" />
            </DataTrigger>
          </Style.Triggers>
        </Style>
      </TextBox.Style>
    </TextBox>
  </Grid>
  <Grid
    Grid.Row="2"
    VerticalAlignment="Center">
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <TextBlock
      Text="{Binding Value1, StringFormat='Value1={0}'}" />
    <TextBlock
      Grid.Column="1"
      Text="{Binding Value2, StringFormat='Value2={0}'}" />
  </Grid>
</Grid>


для удобства здесь используется конвертер:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
public class BoolToIntConverter: IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    => value is int n && n==2;

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    => value is bool b && b ? 2 : 1;
}


Если такой вариант никак не подходит, то способ 2: MultiBinding+IMultiValueConverter. Для Mode=OneWay это делается элементарно, в случае же TwoWay нам в методе ConvertBack нужно знать значение IndexParam, которое взять неоткуда. Можно сделать конвертер, который поддерживает биндинг:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
public class BindableConverter : Freezable, IMultiValueConverter
{
  public BindableConverter()
  {
    BindingOperations.SetBinding(this, DataContextProperty, new Binding());
  }

  public object DataContext
  {
    get => GetValue(DataContextProperty);
    set => SetValue(DataContextProperty, value);
  }

  public static readonly DependencyProperty DataContextProperty =
    FrameworkElement.DataContextProperty.AddOwner(typeof (BindableConverter));

  protected override Freezable CreateInstanceCore()
  {
    throw new NotImplementedException();
  }

  public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  {
    if (!(DataContext is int n))
      return DependencyProperty.UnsetValue;
    return n == 1 ? values[0] : values[1];
  }

  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
    var result = new [] {Binding.DoNothing, Binding.DoNothing};
    if (!(DataContext is int n && value is string s))
      return result;
    if (n == 1)
      result[0] = value;
    else
      result[1] = value;
    return result;
  }
}


и в разметке:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<Window.Resources>
  ............
  <local:BindableConverter
    x:Key="BindableConverter"
    DataContext="{Binding
      RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}},
      Path=DataContext.IndexParam}" />
</Window.Resources>
.........
<TextBox
  Grid.Row="1"
  VerticalAlignment="Center">
  <TextBox.Text>
    <MultiBinding
      Converter="{StaticResource BindableConverter}"
      Mode="TwoWay"
      UpdateSourceTrigger="PropertyChanged">
      <Binding Path="Value1" />
      <Binding Path="Value2" />
    </MultiBinding>
  </TextBox.Text>
</TextBox>


- по моему скромному, излишне усложнено. Гораздо проще в модели завести свойство, возвращающее/устанавливающее Value1 или Value2 в зависимости от IndexParam:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
int _indexParam=1;
public int IndexParam
{
  get => _indexParam;
  set
  {
    if (value!=1 && value!=2)
      throw new ArgumentException();
    _indexParam=value;
    OnPropertyChanged();
    OnPropertyChanged(nameof(CommonValue));
  }
}

public string CommonValue
{
  get => IndexParam == 1 ? Value1 : Value2;
  set
  {
    switch(IndexParam)
    {
      case 1:
        Value1=value;
        break;
      case 2:
        Value2 = value;
        break;
      default:
        throw new ArgumentException();
    }
  }
}


и тогда в разметке будет просто
Код: xml
1.
2.
3.
4.
<TextBox
  Grid.Row="1"
  VerticalAlignment="Center"
  Text="{Binding CommonValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
...
Рейтинг: 0 / 0
04.02.2021, 07:41
    #40041422
Eld Hasp
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
Nechto
Ну это с использованием TextBlock.

А можно как проделать подмену с textbox? Мне нужно чтобы поле можно было редактировать

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<TextBox>
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Setter Property="Text" Value="{Binding Value0}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IndexParam}" Value="1">
                    <Setter Property="Text" Value="{Binding Value1}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding IndexParam}" Value="2">
                    <Setter Property="Text" Value="{Binding Value2}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>



Код: c#
1.
2.
3.
4.
5.
public class Test {
public int Value0 {get;set;}
public int Value1 {get;set;}
public int Value2 {get;set;}
}



В зависимости от выбранного параметра IndexParam, изменялось нужное значение, через один TextBox

А что в этой разметке не работает?

При условии наличии в Контексте Данных сущности Test, реализации в ней и во всех её мутабельных свойствах INPC и добавлении свойства IndexParam должно работать.

Вы пробовали и у вас не получилось?
Или вы показали код даже не проверив его работоспособность?
...
Рейтинг: 0 / 0
04.02.2021, 10:27
    #40041455
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
[quot Eld Hasp#22274449]
Nechto

Вы пробовали и у вас не получилось?
Или вы показали код даже не проверив его работоспособность?


Ну разумеется проверял, если я его написал
...
Рейтинг: 0 / 0
04.02.2021, 11:58
    #40041503
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
Nechto
Ну разумеется проверял, если я его написал

Как-то не так проверял. Всё там прекрасно работает. Если было решено, что не работает непосредственно при наборе текста - так там UpdateSourceTrigger не указан, а по умолчанию он равен LostFocus, т.е. значения в истоник будут отправлены, когда фокус ввода будет из TextBox перемещен куда-то ещё. Чтобы работало сразу при наборе текста, в биндингах нужно указать UpdateSourceTrigger=PropertyChanged.
...
Рейтинг: 0 / 0
04.02.2021, 15:37
    #40041651
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Динамически переназначить свойство TextBox
Сон Веры Павловны
Nechto
Ну разумеется проверял, если я его написал

Как-то не так проверял. Всё там прекрасно работает. Если было решено, что не работает непосредственно при наборе текста - так там UpdateSourceTrigger не указан, а по умолчанию он равен LostFocus, т.е. значения в истоник будут отправлены, когда фокус ввода будет из TextBox перемещен куда-то ещё. Чтобы работало сразу при наборе текста, в биндингах нужно указать UpdateSourceTrigger=PropertyChanged.


Да указывал UpdateSourceTrigger=PropertyChanged. Самое интересное что с TextBlock работает. Нужно посидеть разобраться может, я что-то не так сделал в общей форме.
...
Рейтинг: 0 / 0
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Динамически переназначить свойство TextBox / 9 сообщений из 9, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]