What binding path do I specify if I want WPF to bind to an int? Can I even do that?
TextBox textBox = new TextBox();
textBox.DataContext = myValueType;
textBox.SetBinding(TextBox.TextProperty, new Binding("what do I put here?");
If I clearly understand you, you can write something like this to bind int myValueType property to the textBox Text.
textBox.SetBinding( TextBox.TextProperty, new Binding( "DataContext" )
{ RelativeSource= new RelativeSource( RelativeSourceMode.Self ) } );
Yes you can with:
TextBox textBox = new TextBox();
textBox.DataContext = this;
textBox.SetBinding(TextBox.TextProperty, new Binding("myValueType"));
Here the DataContext variable is the object that contains myValueType property. If the property is declared in the same class you can use this.
If you don't want to set the DataContext of your TextBox, you can use:
textBox.SetBinding(TextBox.TextProperty, new Binding("myValueType") { Source = TheObjectThatContainsMyValueProperty });
If you are not forced to use the code behind then prefer the xaml code. It is eaiser to write and understand these stuff in xaml.
Related
I'm trying to create a label at runtime and connect it's Content property to another TextBox control which is in my UserControl called MyLabelSettings.
This is what I got so far:
Label currCtrl = new Label();
MyLabelSettings currCtrlProperties = new MyLabelSettings();
// Bindings to properties
Binding binding = new Binding();
binding.Source = currCtrlProperties.textBox_Text.Text;
binding.Path = new PropertyPath(Label.VisibilityProperty);
BindingOperations.SetBinding(currCtrl.Content, Label.ContentProperty, binding);
The last row shows an error which I did not figure out how to solve:
The best overloaded method match for 'System.Windows.Data.BindingOperations. SetBinding(System.Windows.DependencyObject, System.Windows.DependencyProperty, System.Windows.Data.BindingBase)' has some invalid arguments
I have in MyLabelSettings the implementation of INotifyPropertyChanged
which has the following code when the TexBox.Text changes
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
InvokePropertyChanged(new PropertyChangedEventArgs("TextChanged"));
}
Is there a better way to bind these 2? Or am I doing something wrong in this one?
Thanks!
The problem is simpler than you realize:
This:
binding.Source = currCtrlProperties.textBox_Text.Text;
binding.Path = new PropertyPath(Label.VisibilityProperty);
BindingOperations.SetBinding(currCtrl.Content, Label.ContentProperty, binding);
Should be this:
//The source must be an object, NOT a property
binding.Source = currCtrlProperties;
//Since the binding source is not a DependencyObject, we using string to find it's property
binding.Path = new PropertyPath("TextToBind");
BindingOperations.SetBinding(currCtrl, Label.ContentProperty, binding);
Before, you were attempting to bind the value to an object's property via a property. Now, you're binding the value to an object's property via an object (:
Notes:
You are attempting to bind the text of a control that exists in an instance of a class you just made.
MyLabelSettings currCtrlProperties = new MyLabelSettings();
I base this assumption off this line:
currCtrlProperties.textBox_Text.Text;
Which appears to contain a text control of some sort. Rather, you want bind the text of a property that exists in an instance of a class you make, not a control.
I have a textbox with xaml markup like this:
<TextBox x:Name="txtHN" Text="{Binding Path=AN}"/>
The above code works perfectly well. But when i change the data binding implementation from XAML to code-behind, It does not work anymore. The following code-behind does not work anymore:
Binding textHnBinding = new Binding();
textHnBinding.Path = new PropertyPath("AN");
txtHN.SetBinding(TextBox.TextProperty, textHnBinding);
I had set the textbox.datacontext to the same collectionviewsource but the code-behind version does not work anymore. I had really no idea what seems to be the culprit.
I use the following code for the CVS.source:
IEnumerable<decimal> ANListWard4 = (from s in context.IPDAN
where ward.Contains(s.CURRENTWARD)
select s.AN).Distinct().OrderBy(n => n);
List<IPDAN> Ward4AN = new List<IPDAN>();
foreach (decimal d in ANListWard4)
{
IPDAN ward4AN1 = new IPDAN();
ward4AN1.AN = d;
Ward4AN.Add(ward4AN1);
}
I set the CVS.Source to Ward4AN. There was no instance where the Ward4AN was null, or has no data.
Check whether the collectionViewSource is not null when you are doing the binding.If the object is null when you are adding the binding, the binding might not work.
Also check whether in loaded event it works or not.
Can you try :
Binding textHnBinding = new Binding("AN");
txtHN.SetBinding(TextBox.TextProperty, textHnBinding);
This is how I done all my binding so I think it should work.
EDIT :
Long time no uses binding so my apologies if I'm wrong again :
Binding textHnBinding = new Binding("AN");
FrameworkElementFactory textHN = new FrameworkElementFactory(typeof(TextBox));
txtHN.SetBinding(TextBox.TextProperty, textHnBinding);
Can you try instantiate your Control like this instead of in Xaml to check if it will work (as me) ? Thank you.
I have xamdatgrid which I add columns dynamically. I am adding a ToolTip to the column using following code.
Binding toolTipBinding = new Binding();
toolTipBinding.Path = new PropertyPath("DataItem.Property1");
Setter toolTipSetter = new Setter();
toolTipSetter.Property = ToolTipProperty;
toolTipSetter.Value = toolTipBinding;
cellValuePresenterStyle.Setters.Add(toolTipSetter);
Using this I was able to display the value of Property1 as the ToolTip. I have another Property in the class (property2). I want to display the values of both Properties in the ToolTip. How can I achieve that
I can't understand why are you not doing it in XAML code. But if you do want to achieve this in using code behind. Then do following steps
Use MultiBinding class to do a binding of tooltip.
create two bindings for two properties (Property1 & Property2) and add them in multibinding you created in step 1 using Add method.
create a converter (IMultiValueConverter) to write a logic to concatinate property1 & property2.
Assign the binding in the setter value as you have already done.
Binding b1=new Binding();
b1.Path = new PropertyPath("DataItem.Property1");
Binding b2=new Binding();
b2.Path = new PropertyPath("DataItem.Property2");
var toolTipBinding = new MultiBinding();
toolTipBinding.Bindings.Add(b1);
toolTipBinding.Bindings.Add(b2);
toolTipBinding.Converter = new ///your converter
I loaded the datatemplate for image column in code behind . Please refer the below code snippet,
FrameworkElementFactory fef = new FrameworkElementFactory(typeof(Image));
Binding bind = new Binding() { Path=new PropertyPath(imagecolumn.MappingName),Converter = new StringToImageConverter(),Mode=BindingMode.TwoWay };
fef.SetBinding(Image.SourceProperty,new Binding(imagecolumn.MappingName));
DataTemplate template = new DataTemplate() { VisualTree = fef };
this.imagecolumn.CellItemTemplate = template;
But my converter is not invoked. I need to load different images in each row of the column . Am i missed anything ? Please share any idea
You instantiate a new Binding but you never use it. Do this:
FrameworkElementFactory fef = new FrameworkElementFactory(typeof(Image));
Binding bind = new Binding() { Path=new PropertyPath("MappingName"),Converter = new StringToImageConverter(),Mode=BindingMode.TwoWay,Source=imagecolumn };
fef.SetBinding(Image.SourceProperty, bind); // here you just created
//another instance of Binding instead of using your bind variable
DataTemplate template = new DataTemplate() { VisualTree = fef };
this.imagecolumn.CellItemTemplate = template;
EDIT:
Have a look at FrameworkElementFactory. In the remarks it sais:
This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; not all of the template functionality is available when you create a template using this class. The recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class.
Maybe you should do it the recommended way.
In my XAML I have this:
<TextBlock Text="{Binding Stats.Scores.Team}" Style="{StaticResource Column_Value_Large}" />
I need to be able to create that TextBlock, in it's entirety, in the codebehind. Here's what I have:
foreach (var Stats in player){
var columnHeaderScore = new TextBlock
{
Style = Application.Current.Resources["Column_Value_Large"] as Style,
};
columnHeaderScore.SetBinding(TextBlock.TextProperty, new Binding
{
Path = new PropertyPath("Stats.Scores.Team"),
});
columnHeaderStackPanel.Children.Add(columnHeaderScore);
}
However, the binding doesn't seem to be working. What's the appropriate way to set the binding in the codebehind?
Edit for context: my goal is to generate a bunch of these text boxes inside a big loop in the codebehind. See my revised example above which now shows the loop. Since I want to do it this way, I don't think there's any possible way for me to do it in the XAML; I would have to set the binding in the codebehind.
I think you use xaml in a wrong way. Why dont you set theTextBlockin the XAML code and bind itsVisibilityto a property or use aStyle. Then you dont have to create the binding in the codebehind.
EDIT: Why don't you use a ItemPanel or something like that to which you bind your collection and give it a DataTemplate which displays the TextBoxes?
I got it.
My problem was using "Path" in SetBinding instead of "Source". The working code looks like this:
foreach (var Stats in player){
var columnHeaderScore = new TextBlock
{
Style = Application.Current.Resources["Column_Value_Large"] as Style,
};
columnHeaderScore.SetBinding(TextBlock.TextProperty, new Binding
{
Source = Stats.Scores.Team,
});
columnHeaderStackPanel.Children.Add(columnHeaderScore);
}