У меня много текстовых полей, распределенных по трем отдельным элементам вкладок, и я хочу дать пользователю возможность выбрать избранные текстовые поля и для удобства отображать их на одном элементе вкладки, который называется «Избранное».
Визуальная часть работает нормально, но я не могу заставить работать привязки, поэтому новое текстовое поле остается пустым.
XAML:
<StackPanel Grid.Row = "3" Grid.Column = "0" x:Name = "SP_TB_DP_ArticleName" x:Uid = "ArticleName" Style = "{StaticResource FavButton}" MouseDown = "FavButton_Click" >
<Label Content = "ArticleName" Style = "{StaticResource Heading2}" />
<Border Background = "Transparent">
<StackPanel Orientation = "Horizontal">
<Path Uid = "FavAdd" Style = "{StaticResource Ico-AddFav}" Fill = "Black"/>
<Path Uid = "FavRem" Style = "{StaticResource Ico-RemFav}" Fill = "Black" Visibility = "Collapsed" />
</StackPanel>
</Border>
</StackPanel>
<TextBox x:Name = "TB_DP_ArticleName" Grid.Row = "4" Grid.Column = "0" Grid.ColumnSpan = "2" Style = "{StaticResource Heading3}" Text = "{Binding Article.Name, UpdateSourceTrigger=PropertyChanged}" />
C# привязки
private void FavButton_Click(object sender, MouseButtonEventArgs e)
{
[... creating textbox and label]
//BindingName is the name of the original textbox ie: TB_DP_ArticleName
DependencyObject OriginalTB = (DependencyObject) this.FindName(BindingName);
BindingBase BB = BindingOperations.GetBindingBase(OriginalTB, TextBox.TextProperty);
var oldBind = BB as Binding;
//Clone Method from other question Link see below *
//BindingBase copyBind= CloneBinding(BB, OriginalTB);
if (OriginalTB != null)
{
Binding binding = new Binding();
binding.Source = this;
binding.Path = oldBind.Path;
binding.Mode = BindingMode.OneWay;
binding.IsAsync = false;
binding.UpdateSourceTrigger = UpdateSourceTrigger.Default;
binding.TargetNullValue = "null";
BindingOperations.SetBinding(tb, TextBox.TextProperty, binding);
//BindingOperations.SetBinding(tb, TextBox.TextProperty, copyBind);
}
//Code to add the Textbox to the Grid
[...]
*) Пробовал cloneMethod от Привязка не имеет метода клонирования, какой эффективный способ его скопировать но это не сработало.
Во время отладки oldBind.Path показывает правильный путь к Article.Name.
Но, в конце концов, программно созданное текстовое поле не будет отображать содержимое исходного текстового поля. Он просто остается пустым.
Да. Все в одном Usercontroll. Просто в другом TabItem.





Вместо того, чтобы пытаться дублировать привязки, просто продублируйте элементы управления (с их привязками к данным, но не с их именами), а затем (привяжите к их свойству видимости), который затем отобразит или скроет элемент управления текстовым полем в зависимости от выбора пользователя.
<TextBox Grid.Row = "4" Grid.Column = "0" Grid.ColumnSpan = "2"
Style = "{StaticResource Heading2}"
Text = "{Binding Article.Name, UpdateSourceTrigger=PropertyChanged}"
Visibility = "{Binding AmIVisible_1}" />
<TextBox Grid.Row = "4" Grid.Column = "0" Grid.ColumnSpan = "2"
Style = "{StaticResource Heading3}"
Text = "{Binding Article.Name, UpdateSourceTrigger=PropertyChanged}"
Visiblity = "{Binding AmIVisible_2}" />
Спасибо за идею другого подхода! Вы имеете в виду дублирование жестко запрограммированным способом? Например, поместить каждое поле данных в этот любимый TabItem, а затем просто переключить видимость? Но разве это довольно неэффективное хранилище неэффективно? Также мне нужно добавить поля данных в двух точках моего кода. И это так много работы для прибл. 300 полей данных. Но все же мне нравится смена точки зрения на это!
Я использовал стратегию видимости, и на самом деле это не проблемы с памятью, а задержка отображения, поскольку каждый элемент отображается на экране ... до 40-50 элементов, и задержка не заметна, но в зависимости от размера элементов рисуется, а затем скрывается, вот в чем проблема. 300 дубликатов будут проблемой.
Ладно, тогда это может быть не лучшим решением. Разве нет способа программно создавать текстовые поля, такие как: <TextBox Text = "{Binding Path=Text, ElementName=secondTextBox, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
Наконец то я понял!
Мне пришлось установить источник привязки к исходному текстовому полю и установить привязку к тексту. Это не решает проблему на 100%, так как это может быть не самое эффективное решение относительно комментария @AlvinfromDiaspar в Синхронизировать два текстовых поля в WPF Но, в любом случае, для моих целей он работает достаточно хорошо.
Что я изменил:
Binding binding = new Binding("Text");binding.Source = (DependencyObject)this.FindName(BindingName);
Полный фрагмент привязки:
String BindingName = inName.Substring(3);
BindingBase BB = BindingOperations.GetBindingBase(
(DependencyObject)this.FindName(BindingName),
TextBox.TextProperty);
var oldBind = BB as Binding;
if (BB != null)
{
//the magic goes here
Binding binding = new Binding("Text");
binding.Source = (DependencyObject)this.FindName(BindingName);
binding.Mode = BindingMode.OneWay;
binding.IsAsync = false;
binding.UpdateSourceTrigger = UpdateSourceTrigger.Default;
binding.TargetNullValue = "null";
BindingOperations.SetBinding(tb, TextBox.TextProperty, binding);
}
«отображать их в другой части моего приложения для удобства». Имеет ли эта другая часть приложения тот же
DataContext, что и исходные текстовые поля?