Binding the x,y location on a Canvas with a ItemsControl
-
I have a simple UserControl that has one dependency property:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}public double LocationX { get { return (double)GetValue(LocationXProperty); } set { SetValue(LocationXProperty, value); } } // Using a DependencyProperty as the backing store for LocationX. This enables animation, styling, binding, etc... public static readonly DependencyProperty LocationXProperty = DependencyProperty.Register("LocationX", typeof(double), typeof(MyUserControl), new PropertyMetadata(0d));
}
The user control just has a single rectangle in it, and I want to bind it to the ItemsControl:
<ItemsControl x:Name="myCanvas">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding LocationX}"/>
<Setter Property="Canvas.Bottom" Value="0"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>Its binded to an ObservableCollection:
public partial class MainWindow : Window
{
ObservableCollection<MyUserControl> myData = new ObservableCollection<MyUserControl>();
public MainWindow()
{
InitializeComponent();
myData.Add(new MyUserControl() { LocationX = 50 });
myData.Add(new MyUserControl() { LocationX = 350 });
myCanvas.ItemsSource = myData;
}
}The Canvas.Bottom is set according to the value given, but the value I want to be binded won't work correctly. What Am I doing wrong here?
-
I have a simple UserControl that has one dependency property:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}public double LocationX { get { return (double)GetValue(LocationXProperty); } set { SetValue(LocationXProperty, value); } } // Using a DependencyProperty as the backing store for LocationX. This enables animation, styling, binding, etc... public static readonly DependencyProperty LocationXProperty = DependencyProperty.Register("LocationX", typeof(double), typeof(MyUserControl), new PropertyMetadata(0d));
}
The user control just has a single rectangle in it, and I want to bind it to the ItemsControl:
<ItemsControl x:Name="myCanvas">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding LocationX}"/>
<Setter Property="Canvas.Bottom" Value="0"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>Its binded to an ObservableCollection:
public partial class MainWindow : Window
{
ObservableCollection<MyUserControl> myData = new ObservableCollection<MyUserControl>();
public MainWindow()
{
InitializeComponent();
myData.Add(new MyUserControl() { LocationX = 50 });
myData.Add(new MyUserControl() { LocationX = 350 });
myCanvas.ItemsSource = myData;
}
}The Canvas.Bottom is set according to the value given, but the value I want to be binded won't work correctly. What Am I doing wrong here?
Damn, answering my own question, again: Well, all I need to do is to set the x:Name="MyControl" in the user control, and in the binding set ElementName=MyControl, Path="LocationX"
-
Damn, answering my own question, again: Well, all I need to do is to set the x:Name="MyControl" in the user control, and in the binding set ElementName=MyControl, Path="LocationX"
A much better approach would be,
<... Value="{Binding Path=LocationX, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
-
A much better approach would be,
<... Value="{Binding Path=LocationX, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
Yeah, I did try that too, and it worked fine for my other controls when the Dependency Property was within the Control that I wanted to bind to. Btw, you don't need the x:Type to make it work:
Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=XLabel}"
But as soon as I had a collection of different user controls and I wanted to access them, I had to say ElementName for some reason. I guess it was because it couldn't find the correct property in the first Ancestor type.
-
A much better approach would be,
<... Value="{Binding Path=LocationX, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
Why would this be a better approach?
This space for rent
-
Why would this be a better approach?
This space for rent
You might set the name of the user control to something different when its an element in your window. Setting the name property in the user control will still work though since it is initialized before the containing window. Using
Binding.RelativeSource
is a suitable option."As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
-
You might set the name of the user control to something different when its an element in your window. Setting the name property in the user control will still work though since it is initialized before the containing window. Using
Binding.RelativeSource
is a suitable option."As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
I ended up by setting the x:Name and specify the ElementName as I said, but I would really like to know how to implement the RealativSource in my project. A simple WPF LineChart control[^] I couldn't see exactly how to do it.
-
I ended up by setting the x:Name and specify the ElementName as I said, but I would really like to know how to implement the RealativSource in my project. A simple WPF LineChart control[^] I couldn't see exactly how to do it.
My answer was in response to Pete's question.
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
-
A much better approach would be,
<... Value="{Binding Path=LocationX, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
Ah, posted it in the wrong place. I couldn't make it work properly. It simply wouldn't find the x:Type UserControl. It refused to bind, and I don't know how to fix it.