2

I have a lot of textboxes distributed over three individual TabItems and I want to give the User the option to choose favorite texboxes and display them on one tabItem called Favorites for convenience.

The visual part works fine, but I can't seem to get the bindings working, so the new Textbox stays empty.

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# of the binding

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 
[...]

*) I tried the cloneMethod from Binding does not have a Clone method, whats an effective way to copy it but that didnt work aswell.

During debug oldBind.Pathshows the correct path to Article.Name.

But in the end the programmatically created textbox won't show the content of the original Textbox. It simply stays empty.

x3Ro
  • 51
  • 6
  • 1
    "display them on another part of my app for convenience" does that other part of the app have the same `DataContext` as the original TextBoxes? – Lithium May 29 '18 at 12:20
  • Yes. Its all in one Usercontroll. Just in another TabItem. – x3Ro May 29 '18 at 12:29

2 Answers2

1

Finally I got it!

I had to set the source of the binding to the original TextBox and set the Binding to Text. This doesnt answer the problem 100%, as this might not be the most effiecent solution regarding @AlvinfromDiaspar comment in Keep two textboxes synchronized in WPF But anyhow, it works well enough for my purposes.

What I changed:

Binding binding = new Binding("Text"); binding.Source = (DependencyObject)this.FindName(BindingName);

Whole snippet of the binding:

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);
 }
x3Ro
  • 51
  • 6
0

Instead of trying to duplicate bindings, simply duplicate the controls (with their data bindings but not their names) and then (bind to their visibility property) which will then show or hide the textbox control based on a user selection.

<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}" />
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
  • Thanks for the idea of an different approach! Do you mean duplicate in a hard-coded way? Like put every datafield inside that favorite TabItem and then just toggle the visibility? But isn't that pretty storage inefficient? Also I'd need to add datafields at two points in my code. AND thats so much work for aprox. 300 datafields. But still I like the change of perspective on that! – x3Ro May 29 '18 at 13:22
  • I've used the visibility strategy and it's not memory issues actually , but display lag, as each item is drawn on the screem... up to 40-50 items and the delay is not noticible, but depending on the size of the items being drawn then hidden that is where the issue is. 300 duplicates would be an issue. – ΩmegaMan May 29 '18 at 14:21
  • Okay so that might not be the best solution then. Isn't there a way to programmatically buid textboxes like: ` – x3Ro May 30 '18 at 06:51