How to make a binding on a nested target property, like Shape.Stroke.Color in WPF without using XAML ?
For a simple property I'm using a code looking like this :
var binding = new Binding("mySourceProperty");
binding.Source = mySourceObject;
myTargetObject.SetBinding(myTargetProperty, binding);
Where myTargetProperty can be, for example, Shape.StrokeProperty.
But now, how can I do the same thing on the ColorProperty of the Stroke of a Shape ?
Provided that the Shape's Stroke property holds a SolidColorBrush, you can use the static BindingOperations.SetBinding method:
var shape = new Path(); // or whatever
var binding = new Binding { Source = Colors.Red }; // or whatever
BindingOperations.SetBinding(shape.Stroke, SolidColorBrush.ColorProperty, binding);
Related
Hi I want to set the Text property of a Textbox by code behind. At the moment I do using XAML:
<TextBox x:Name="txtFilter" Text="{Binding FiltroFunzioni, Mode=OneWayToSource}" Grid.Row="0" />
As test I did this:
Binding b = new Binding();
b.Mode = BindingMode.OneWayToSource;
b.Path = new PropertyPath("Text"); //??
b.Source = PageViewModel.FiltroFunzioni;
BindingOperations.SetBinding(txtFilter, TextBlock.TextProperty, b);
The variable "FiltroFunzioni" is a string defined as property:
private string _filtroFunzioni = "";
public string FiltroFunzioni
{
get { return _filtroFunzioni; }
set
{
_filtroFunzioni = value;
RaisePropertyChanged("FiltroFunzioni");
_functionsView.Refresh();
}
}
Basically I dunno what kind of value should I set as PropertyPath. Any ideas?
You don't need the PropertyPath here. If you just remove it, your binding should work.
That being said, you should bind in XAML wherever possible.
If your issue is that changes to FiltroFunzioni don't update your textbox, that's because your binding is specifically declared as OneWayToSource: that means that changing the UI changes the source, but changing the source doesn't change the UI. If that isn't what you want, set the Mode to something else, like "TwoWay" - then changes to the source change the UI, AND changes to the UI change the source.
EDIT:
If you really want to bind from your ViewModel instead of just using XAML, TwoWay binding requires utilizing the Path for some reason, when binding through C#. Either of the following solutions work:
b.Source = FiltroFunzioni;
b.Path = new PropertyPath(".");
b.Source = this;
b.Path = new PropertyPath("FiltroFunzioni");
Note that with TwoWay binding you have to either initialize your FiltroFunzioni by setting the TextBox.Text property in your XAML, or setting FiltroFunzioni after the binding was initialized. Otherwise, WPF will immediately override it from the (by default empty) Text in your TextBox.
I want to bind the background of a WPF Rectangle to the Brush property of another element.
The initialization looks like this:
MazeElement nextElement = new MazeElement();
nextElement.Position = new Point(xIndex, yIndex);
nextElement.BackgroundColor = Brushes.Aqua;
MazeElements.Add(nextElement);
Binding bg = new Binding {Source = MazeElements[Index(xIndex, yIndex)]};
Rectangle nextRect = new Rectangle();
nextRect.Height = MazeGridSize;
nextRect.Width = MazeGridSize;
nextRect.Fill = Brushes.White;
nextRect.Stroke = Brushes.Gray;
nextRect.StrokeThickness = 2;
nextRect.SetBinding(Shape.FillProperty, bg);
temp.Children.Add(nextRect);
Canvas.SetLeft(nextRect, xIndex * MazeGridSize);
Canvas.SetTop(nextRect, yIndex * MazeGridSize);
Where is my mistake? I don't understand how to use the Binding from the C# side.
First, you are not providing us with enough information. We cannot see the full nature of the type MazeElement. But I assume that the BackgroundColor is a Property on the MazeElement class
Second, the binding has a Source, an object in your case nextElement, and the a PropertyPath, in your case the BackgroundColor. Therefore your binding object should be:
Binding bg = new Binding {Source = nextElement, Path = new PropertyPath("BackgroundColor") };
In your case the source property is of the same type as the target dependency property, so the above will do what you want. If it was not the case, you can set a converter on the binding - Look that up, if you need that in another situation
I'm able to bind the property from entity to a listview content page element as below,
highlightGrid.SetBinding(IsVisibleProperty, "IsPaymentPlanEnding");
But I want to how do I bind this "IsPaymentPlanEnding" property value to a variable. Trying with the below code, but it is throwing a compilation error.
bool IsPaymentPlanEnding = BindingContext.GetBindingValue("IsPaymentPlanEnding");
Please let me know how do I bind the entity property value to variable.
You can store your binding in a variable like this:
BindingBase paymentPlanEndingBinding = new Binding("IsPaymentPlanEnding");
Then reference it when doing the actual binding:
highlightGrid.SetBinding(IsVisibleProperty, paymentPlanEndingBinding);
I wrote a simple unit test for that:
[Test]
public void BindingBase_test()
{
MockForms.Init();
BindingBase binding = new Binding("Value");
var pickerItem = new PickerSearchItem {Value = "the_value"};
var label = new Label {BindingContext = pickerItem};
label.SetBinding(Label.TextProperty, binding);
label.Text.ShouldBe("the_value");
}
Your BindingContext needs to Implement INotifyPropertyChanged.
And the BindingContext should hold a property (of type bool) called IsPaymentPlanEnding.
Then you can just leave the line as it is:
highlightGrid.SetBinding(IsVisibleProperty, "IsPaymentPlanEnding");
Learn about Bindings
I have a ScatterViewItem, which contains a UserControl. I'm trying to bind the MinWidth of the ScatterViewItem to the UserControl.
ScatterViewItem svi = new ScatterViewItem();
MyUserControl myUserControl = new MyUserControl();
//Make UC follow SVI's size. This code works.
myUserControl.SetBinding(UserControl.WidthProperty, svi.Width.ToString());
myUserControl.SetBinding(UserControl.HeightProperty, svi.Height.ToString());
//Make SVI follow UC's Min size. This doesn't work.
svi.SetBinding(ScatterViewItem.MinWidthProperty, myUserControl.MinWidth.ToString());
svi.SetBinding(ScatterViewItem.MinHeightProperty, myUserControl.MinHeight.ToString());
svi.Content = myUserControl;
myScatterView.Items.Add(svi);
Why is it that binding UC to SVI works and not the other way? How do I bind the MinWidth of the SVI to the UC then?
The SetBinding method has 2 overloads (source: http://msdn.microsoft.com/en-us/library/ms598270(v=vs.110).aspx):
SetBinding(DependencyProperty, String)
SetBinding(DependencyProperty, BindingBase)
What you are trying to achieve by using the ToString() is not working, since the ToString() converts the value of the (Min)Width and (Min)Height properties to a string (for example 500.0 => "500.0"). The SetBinding overload that accepts a string as second parameter expects that string to be a property name or a path to the property.
What you probably want, is "MinWidth", "Width", "MinHeight" or "Height":
myUserControl.SetBinding(UserControl.WidthProperty, "Width");
myUserControl.SetBinding(UserControl.HeightProperty, "Height");
svi.SetBinding(ScatterViewItem.MinWidthProperty, "MinWidth");
svi.SetBinding(ScatterViewItem.MinHeightProperty, "MinHeight");
Edit: this is the correct version, using the other overload, since the previous piece of code doesn't know where to find the specified properties.
Binding widthBinding = new Binding("Width");
widthBinding.Source = myUserControl;
svi.SetBinding(ScatterViewItem.MinWidthProperty, widthBinding);
Binding heightBinding = new Binding("Height");
heightBinding.Source = myUserControl;
svi.SetBinding(ScatterViewItem.MinHeightProperty, heightBinding);
To bind your ScatterViewItem's MinWidth to your usercontrol's MinWidth, you need to create a binding with the source set to the usercontrol and path set to "MinWidth". This binding is then assigned to the ScatterViewItem with SetBinding.
// Create Binding
Binding b = new Binding("MinWidth");
b.Source = myUserControl;
// Assign Binding to ScatterViewItem
svi.SetBinding(ScatterViewItem.MinWidthProperty, b);
I try to bind a translateTransform and a compositeTransform together in silverlight 4 in the code (c#). I can't do this in xaml because the UIelements are loaded dynamically. I just need the Xoffset. The compositeTransform is the source. I have the flowing code, but it doesn't work:
TranslateTransform trans = new TranslateTransform();
Binding transBind = new Binding("Value");
transBind.Source = ((CompositeTransform)SchedulePanel.RenderTransform);
BindingOperations.SetBinding(trans, TranslateTransform.XProperty, transBind);
line.TextChannelName.RenderTransform = trans;
Thanks
Looks to me as though:-
Binding transBind = new Binding("Value");
should be
Binding transBind = new Binding("TranslateX");
a composite transform does not have a "Value" property.
Since TranslateTransform is not a FrameworkElement, in order to be the target of a binding it must meet one of these conditions (from MSDN):
In Silverlight 4, the target can also be a DependencyProperty of a DependencyObject in the following cases:
The DependencyObject is the value of a property of a FrameworkElement.
The DependencyObject is in a collection that is the value of a FrameworkElement property (for example, the Resources property).
The DependencyObject is in a DependencyObjectCollection.
So try setting the trans TranslateTransform as the Transform of TextChannelName before setting the binding so that at the moment of setting the binsing, the target.
Try:
TranslateTransform trans = new TranslateTransform();
line.TextChannelName.RenderTransform = trans;
Binding transBind = new Binding("Value");
transBind.Source = ((CompositeTransform)SchedulePanel.RenderTransform);
BindingOperations.SetBinding(trans, TranslateTransform.XProperty, transBind);