WPF Binding to Field - wpf

I have tried nearly everything I found on google. But nothing works.
I have this Xaml:
<UserControl x:Class="Controller.General.Led"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Ellipse Name="ellipse" Fill="{Binding ElementName=Led, Path=backColor}" Stroke="Black" StrokeThickness="3">
</Ellipse>
</Grid>
And this Code:
public partial class Led : UserControl
{
public Brush backColor = Brushes.Red;
public Led()
{
InitializeComponent();
}
}
So why doesn't this work?
I also tried a lot of other solutions but nothing is working.

A couple things wrong here, first you can't just set ElementName to a class. A quick easy way to fix this is just set the data context of your user control to itself, since it appears that's where the property you want to bind dwells. Also change the public variable to a PROPERTY (Binding does not work otherwise!)
public partial class Led : UserControl
{
public Brush backColor{get; set;}
public Led()
{
InitializeComponent();
this.DataContext = this;
backColor = Brushes.Red;
}
}
Next just alter your xaml to simply read...
<Ellipse
Name="ellipse"
Fill="{Binding backColor}"
Stroke="Black"
StrokeThickness="3"
/>

When you use ElementName=Led, you're telling WPF to look for an element named Led, however you haven't declared an element with that name.
KDiTraglia's answer is the correct way to go, but setting a name for your user control would also work:
<UserControl x:Name="Led" ...>
....
</UserControl>

Related

How to make this named ComboBox in XAML to stop giving a compiler error?

I am trying to make a zoomable toolbar which contains, besides other elements, a ComboBox.
I have a named ComboBox as the content of an instance of a local:ZoomableStackPanel custom control class that inherits from StackPanel and adds a ZoomFactor property which is specified in the IZoomableControl interface. There is a compiler error.
The error seems to be caused by the custom control implementation, but I do not know what is missing. If I replace local:ZoomableStackPanel with a normal StackPanel, there isn't any error. I also tried without any IsSelected ComboBoxItem-s, and the error remains.
MainWindow.xaml
<Window x:Class="cs_wpf_test_14.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:cs_wpf_test_14"
mc:Ignorable="d" Height="60" Width="200">
<local:ZoomableStackPanel Orientation="Horizontal">
<ComboBox Name="MyComboBox">
<ComboBoxItem IsSelected="True">abc</ComboBoxItem>
<ComboBoxItem>def</ComboBoxItem>
<ComboBoxItem>ghi</ComboBoxItem>
</ComboBox>
</local:ZoomableStackPanel>
</Window>
ZoomableStackPanel
XAML
<StackPanel x:Class="cs_wpf_test_14.ZoomableStackPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:cs_wpf_test_14"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel.LayoutTransform>
<ScaleTransform
ScaleX="{Binding
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=StackPanel},Path=ZoomFactor}"
ScaleY="{Binding
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=StackPanel},Path=ZoomFactor}">
</ScaleTransform>
</StackPanel.LayoutTransform>
</StackPanel>
Code-behind
/// <summary>
/// Interaction logic for ZoomableStackPanel.xaml
/// </summary>
public partial class ZoomableStackPanel : StackPanel, IZoomableControl
{
public ZoomableStackPanel()
{
InitializeComponent();
}
public static readonly DependencyProperty ZoomFactorProperty =
DependencyProperty.Register("ZoomFactor", typeof(decimal), typeof(ZoomableStackPanel),
new FrameworkPropertyMetadata(1M));
public decimal ZoomFactor
{
get
{
return (decimal)GetValue(ZoomFactorProperty);
}
set
{
SetValue(ZoomFactorProperty, value);
}
}
}
The interface
public interface IZoomableControl
{
decimal ZoomFactor { get; set; }
}
I expected the test project to build successfully but there is this compiler error:
Cannot set Name attribute value 'MyComboBox' on element 'ComboBox'. 'ComboBox' is under the scope of element 'ZoomableStackPanel', which already had a name registered when it was defined in another scope.

Accessing dependency property in the same control xaml

In a Wpf Application i have a main window.
I have added a user control to the same project.
In the user control's .xaml.cs file a Dependency property ( "Value" name of the property ) is added.
I would like to access the defined dependency property in the usercontrol.xaml.
I know i can do the same while creating the control instance either in window.xaml or some other user control.
But is it possible to access the dependency property defined in .xaml.cs in .xaml?
Question updated based on Vivs answer
Ok. I mentioned my question wrongly. Nevertheless even i was not aware of accessing. But my actual intended question is it possible to set the dependency property from .xaml. some thing like from the example given above,
<Grid CustomBackground ="{Binding Path= BackgroundColor}" />
Or
<Grid CustomBackground ="Blue" />
Is it possible to set the custom dependency properties like this in the same .xaml?
Yes it is possible.
something like:
.xaml
<UserControl x:Class="MvvmLight26.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}, Path=CustomBackground}" />
</UserControl>
and .xaml.cs:
public partial class UserControl1 : UserControl {
public static readonly DependencyProperty CustomBackgroundProperty =
DependencyProperty.Register(
"CustomBackground",
typeof(Brush),
typeof(UserControl1),
new FrameworkPropertyMetadata(Brushes.Tomato));
public UserControl1() {
InitializeComponent();
}
public Brush CustomBackground {
get {
return (Brush)GetValue(CustomBackgroundProperty);
}
set {
SetValue(CustomBackgroundProperty, value);
}
}
}
Alternate:
If you say have the DataContext of the UserControl as itself like:
public UserControl1() {
InitializeComponent();
DataContext = this;
}
then in your xaml you could just go with:
<Grid Background="{Binding Path=DataContext.CustomBackground}" />
Update:
For the new question,
Not quite directly.
You can "set" the value if the custom DP is registered as an attached property(Do remember an attached property is not the same as a normal DP in it's behavior and scope.)
If you want to keep it as a normal DP, then you can keep UserControl1 from the original answer same as it is(just the DP part. You need to remove the xaml part of it and make it a non-partial class in the code-behind) and then derive it to a new UserControl.
something like:
<local:UserControl1 x:Class="MvvmLight26.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
CustomBackground="Blue"
mc:Ignorable="d">
<Grid />
</local:UserControl1>
You can ofc name UserControl1 as something like "BaseUserControl" or so to make it obvious that it's not intended for direct usage.
You can set the value from the UserControl.Style in the same xaml as well.
xaml:
<UserControl x:Class="MvvmLight26.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Style>
<Style>
<Setter Property="local:UserControl1.CustomBackground"
Value="Blue" />
</Style>
</UserControl.Style>
<Grid Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}, Path=CustomBackground}" />
</UserControl>

Fail to do binding to image

i have simple class
public class A
{
public ImageSource imageSource
{
get;
set;
}
}
page class:
Public class page : Page
{
A a_class = new A();
}
And simple silverlight page that contain object type A.
In this page i have Image that i want to bind to imageSource of A.
So i wrote it and its not working.
<Image x:Name="Image_" Stretch="Fill"
Source="{Binding imageSource}" DataContext="{StaticResource a_class }"/>
How i need to write it so it will work fine ?
Thanks for any help.
The StaticResource markup extension doed not access fields or properties of the class that the Xaml is loaded into. Delete the line:-
A a_class = new A();
Instead instance A in a resource dictionary:-
<UserControl x:Class="YourApplication.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:local="clr-namespace:YourApplication"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<local:A x:Key="a_class" />
</UserControl>
<Grid x:Name="LayoutRoot">
<Image x:Name="Image_" Stretch="Fill"
Source="{Binding imageSource}" DataContext="{StaticResource a_class}"/>
</Grid>
</UserControl>
Note is you want the Image control to track changes made to the imageSource property you need A to implement INotifyPropertyChanged.

WPF databinding: Why doesn't my copy display on the screen?

What simple thing am I missing here? Why doesn't my copy display on the screen?
<Window x:Class="DeleteThis.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" >
<Grid>
<StackPanel>
<TextBlock Text="{Binding Path=SomeCopy}" Height="35" Width="100" Margin="10"/>
</StackPanel>
</Grid>
and my code-behind.
public partial class MainWindow : Window
{
private string _someCopy;
public string SomeCopy
{
get
{
return _someCopy;
}
set
{
_someCopy = value;
}
}
public MainWindow()
{
InitializeComponent();
SomeCopy = "why doesn't this display";
}
}
You never set the DataContext of the Window. Change your XAML to this...
<TextBlock Text="{Binding}" Height="35" Width="100" Margin="10"/>
...and change your code behind to add the DataContext line...
public MainWindow()
{
InitializeComponent();
SomeCopy = "why doesn't this display";
this.DataContext = SomeCopy;
}
Your current issue has nothing to do with needing a DependencyProperty as mentioned in the other answers.
WPF never finds out that the property changed.
To fix it, you can turn the property into a dependency property.
EDIT: You also need to bind to the property on the Window itself, like this
<TextBlock Text="{Binding Path=SomeCopy, RelativeSource={RelativeSource Self}}" ... />
SLaks's answer is the correct one. But making dependency properties manually is annoying, so I link you to my favorite solution: A custom PostSharp NotifyPropertyChangedAttribute that, when used in conjunction with PostSharp, makes all the properties of any given class into dependency properties.

How do you prevent a base class property from rendering in a DataForm?

Please excuse this novice question, but I'm ramping up on Silverlight and MVVM Light. I created a view called MyView.xaml and a corresponding MyViewModel.cs.
MyView.xaml
<navigation:Page x:Class="Dashboard.Views.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Dashboard.ViewModels"
xmlns:controls="clr-namespace:Dashboard.Controls"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="MyView Page" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<navigation:Page.Resources>
<vm:MyViewModel x:Key="MyViewModel" />
</navigation:Page.Resources>
<navigation:Page.DataContext>
<Binding Source="{StaticResource MyViewModel}"/>
</navigation:Page.DataContext>
<Grid x:Name="LayoutRoot">
<StackPanel Orientation="Vertical" Style="{StaticResource LoginControlsStackPanelStyle}" HorizontalAlignment="Center" VerticalAlignment="Center">
<toolkit:DataForm Name="dataForm1" CurrentItem="{Binding}"/>
</StackPanel>
</Grid>
MyViewModel.cs
namespace Dashboard.ViewModels
{
public class MyViewModel : ViewModelBase
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
When I run the project, my form renders the IsInDesignMode property. I obviously do not want this. How can I prevent the base class property from rendering in the dataform?
Thanks.
Andrew
If you only want to prevent one filed from showing up, you can subscribe to the AutoGeneratingField event and set the Cancel flag on the events args to true. If you want to implement your own layout, you can set the AutoGeneratingFields flag to false and provide your own templates.

Resources