Get property value WPF - c#

I am trying get a value from a property but isn't working I always get a null value.
string imageNormal;
public static readonly DependencyProperty ImageNormalProperty =
DependencyProperty.Register("ImageNormal", typeof(string), typeof(MainWindow));
public string ImageNormal
{
get { return (string)GetValue(ImageNormalProperty); }
set { SetValue(ImageNormalProperty, value); }
}
public ButtonImageStyle()
{
InitializeComponent();
DataContext = this;
Console.WriteLine("Path: " + ImageNormal);
}
Xaml ButtonImageStyle.xaml:
<Image Source="{Binding ImageNormal}" Stretch="None" HorizontalAlignment="Center" VerticalAlignment="Center" />
Xaml MainWindow.xaml:
<local:ButtonImageStyle HorizontalAlignment="Left" Height="60" VerticalAlignment="Top" Width="88" ImageNormal="C:/Users/Xafi/Desktop/add.png"/>
I always obtain next output:
Path:

since your ImageSource is have to be binded to it's parent DependencyProperty (which is defined to your code behind), you have to define your binding to be rlative to your UserControl (let's name it This). Thus please try to change your xaml in the next way:
Xaml code
<UserControl x:Class="SomeBindingExampleSOHelpAttempt.ButtonImageStyle"
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" x:Name="This">
<Grid>
<Image Source="{Binding ElementName=This, Path=ImageNormal, UpdateSourceTrigger=PropertyChanged}"
Stretch="None" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid></UserControl>
Here you can find an additional perfect answer.
Regards.

Related

Simple popup dialog in WPF (overlay inside Window)

I'm working on a modal dialog popup (I'm not sure about the exact UX term) that is displayed inline, inside of a control or window with darkened background.
Visual example
What I tried is putting a <ContentPresenter /> inside the XAML of the popup and then just instantiate it like this:
<local:Popup Grid.RowSpan="2">
<TextBlock Text="Popup test..." />
</local:Popup>
However, the XAML replaces the entire Popup XAML instead of being placed where the ContentPresenter is.
Q: How is the ContentPresenter here used properly?
Popup.xaml
<ContentControl
x:Class="[...].Popup"
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:[...]"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="300">
<Grid Background="#7f000000">
<Grid Background="White" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Margin="20">
<TextBlock Text="{Binding Title, RelativeSource={RelativeSource AncestorType=UserControl}}" FontSize="20" />
<ContentPresenter />
</StackPanel>
</Grid>
</Grid>
</ContentControl>
Popup.xaml.cs
using System.Windows;
namespace [...]
{
public partial class Popup : ContentControlBase
{
public static DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(Popup));
public string Title
{
get
{
return (string)GetValue(TitleProperty);
}
set
{
SetValue(TitleProperty, value);
}
}
public Popup()
{
InitializeComponent();
}
}
}
The content of your Popup should be defined as a ControlTemplate for the ContentPresenter to work as expected here. Please refer to the following sample code.
Popup.xaml:
<ContentControl
x:Class="WpfApplication1.Popup"
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:WpfApplication1"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="300"
x:Name="popup">
<ContentControl.Template>
<ControlTemplate TargetType="local:Popup">
<Grid Background="#7f000000">
<Grid Background="White" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Margin="20">
<TextBlock Text="{Binding Title, ElementName=popup}" FontSize="20" />
<ContentPresenter />
</StackPanel>
</Grid>
</Grid>
</ControlTemplate>
</ContentControl.Template>
Popup1.xaml.cs.
public partial class Popup : ContentControl
{
public static DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(Popup));
public string Title
{
get
{
return (string)GetValue(TitleProperty);
}
set
{
SetValue(TitleProperty, value);
}
}
public Popup()
{
InitializeComponent();
}
}
}
Window1.xaml:
<local:Popup Title="Title...">
<TextBlock>Text...</TextBlock>
</local:Popup>

Custom property and communicating data between view-models

I'm trying to build a simple app that has a control that defines player's name and their style. This control is reused for player 1 and player 2. The first goal is to set two radio button groups so that each player gets to select accordingly. The second is to communicate the data from this control to the main page's view model. How do I accomplish these things?
Here's what the control looks like:
The following is the project structure:
Player.cs simply holds reference to the player's style and their name
namespace temp
{
class Player
{
// offensive / defensive
public string Style { get; set; }
public string Name { get; set; }
}
}
It also acts as the view model for PlayerInfoControl. Here's the code for it:
<UserControl x:Class="temp.Controls.PersonInfoControl"
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:temp.Controls"
xmlns:vm="clr-namespace:temp"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<vm:Player x:Key="ViewModel" />
</UserControl.Resources>
<Grid DataContext="{StaticResource ViewModel}">
<StackPanel Orientation="Horizontal" Height="50">
<StackPanel Margin="0,0,15,0" VerticalAlignment="Center">
<RadioButton Content="Offense" GroupName="{Binding Group}" />
<RadioButton Content="Defense" GroupName="{Binding Group}" />
</StackPanel>
<StackPanel Margin="0,0,15,0" Orientation="Horizontal" VerticalAlignment="Center">
<Label Content="Name" />
<TextBox Width="100" Height="25" Text="{Binding Name}"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
MainWindow is a simple grid that defines the playerInfoControl twice
<Window x:Class="temp.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:temp"
xmlns:controls="clr-namespace:temp.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainWindowViewModel x:Key="ViewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource ViewModel}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="160" />
</Grid.RowDefinitions>
<controls:PersonInfoControl Grid.Row="0" Group="p1" />
<controls:PersonInfoControl Grid.Row="1" Group="p2" />
</Grid>
</Window>
Lastly, there's MainWindowViewModel that I need to relay the data to, that's captured by PlayInfoControl.
namespace temp
{
class MainWindowViewModel
{
Player Player1 = new Player();
Player Player2 = new Player();
}
}
I'm first trying to solve setting the group. I created a custom dependency property, however by app fails to build because of it and I'm not sure what I'm doing wrong.
public partial class PersonInfoControl : UserControl
{
public PersonInfoControl()
{
InitializeComponent();
}
public string Group
{
get { return (string)GetValue(GroupProperty); }
set { SetValue(GroupProperty, value); }
}
// Using a DependencyProperty as the backing store for Group. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GroupProperty =
DependencyProperty.Register("Group", typeof(string), typeof(Player), new PropertyMetadata(0));
}
This is what the error looks like:
You need to use the correct type for the default value of your dependency property. In your case its 0 which cannot be assigned to a string. Replace
new PropertyMetadata(0));
with
new PropertyMetadata(string.Empty));

WPF XAML Binding Not Picking Up DependencyProperty Value

I have a really simple UserControl
<UserControl x:Class="Namespace.Views.TabViews.TabViewTemplate"
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="900" d:DesignWidth="880"
d:DataContext="{d:DesignData Type=TabViewTemplate}">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderBrush="#FFB31B16" BorderThickness="0,0,0,1" Margin="20" VerticalAlignment="Top">
<TextBlock VerticalAlignment="Bottom" FontSize="20" LineHeight="24" Margin="0,0,0,5" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Title}"/>
</Border>
<Border Grid.Row="1" Padding="20">
<ContentPresenter ContentSource="Content"/>
</Border>
</Grid>
</ControlTemplate>
</UserControl.Template>
</UserControl>
and it's code behind
using System;
using System.Windows;
using System.Windows.Markup;
namespace Namespace.Views.TabViews {
/// <summary>
/// Interaction logic for TabViewTemplate.xaml
/// </summary>
[ContentProperty("Content")]
public partial class TabViewTemplate {
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(TabViewTemplate),
new FrameworkPropertyMetadata(
"Sample",
FrameworkPropertyMetadataOptions.AffectsRender,
OnTitleChanged)
);
private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var control = d as TabViewTemplate;
if (control != null) control.Title = (string)e.NewValue;
}
public TabViewTemplate() {
InitializeComponent();
}
public static void SetTitle(TabViewTemplate element, string value) {
element.SetValue(TitleProperty, value);
}
public static string GetTitle(TabViewTemplate element) {
return (string) element.GetValue(TitleProperty);
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
}
}
I make use of that code like this
<UserControl x:Class="Namespace.Views.TabViews.WelcomeTabView"
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:gif="http://wpfanimatedgif.codeplex.com"
xmlns:tabViews="clr-namespace:Namespace.Views.TabViews"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<tabViews:TabViewTemplate Title="Welcome">
<Grid>
<Border BorderBrush="Coral" BorderThickness="2" Margin="0">
<Image gif:ImageBehavior.AnimatedSource="../../Resources/js_cfg_install_howto.gif"/>
</Border>
</Grid>
</tabViews:TabViewTemplate>
</UserControl>
However the value "Welcome" gets set via the property -- I see this via a breakpoint on the property setter -- however the get is never called. I have used all sorts of Binding combinations, none of which work. What is the "correct" way to set the TextBlock Text by way of a DependencyProperty? Thanks!
It was working. My TextBlock needed a Foreground of Black in order to see the text.

How do I add additional properties to a text box

I'm trying to add a couple of custom properties to textboxes in my application , it will help me reduce the lines of code needed drastically..
C# Code for adding the property
class HorizonTextBoxExt:TextBox
{
public HorizonTextBoxExt() : base() { }
public bool BoundToDataGrid
{
get { return (bool)this.GetValue(BoundToDataGridProperty); }
set { this.SetValue(BoundToDataGridProperty, value); }
}
public static readonly DependencyProperty BoundToDataGridProperty =
DependencyProperty.Register(
"BoundToDataGrid",
typeof(bool),
typeof(HorizonTextBoxExt),
new UIPropertyMetadata(false)
);
}
"Error 3 The attachable property 'BoundToDataGrid' was not found in
type HorizonTextBoxExt'.
is the error I get in the xaml wind of the wpf designer
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Local ="clr-namespace:WpfApplication7"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox HorizontalAlignment="Left" Height="63" Margin="90,47,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="225" Local:HorizonTextBoxExt.BoundToDataGrid="true" />
</Grid>
</Window>
Replace this:
<Grid>
<TextBox /* ... */ Local:HorizonTextBoxExt.BoundToDataGrid="true" />
</Grid>
with this:
<Grid>
<Local:HorizonTextBoxExt /* ... */ BoundToDataGrid="true" />
</Grid>

Why does my Custom UserControl's dependency property not work with dynamically binding?

My Custom UserControl's dependency property will bind correctly if the value is statically defined in the XAML calling it, like this:
TextBoxText="myName"
but not if the value is bound dynamically itself:
TextBoxText="{Binding ItemTypeIdCode}"
There is my full Code.
Custom UserControl XAML:
<UserControl
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"
mc:Ignorable="d"
x:Class="TestUserControl.UserControl1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
x:Name="UserControl" Height="22" Width="282">
<Grid x:Name="LayoutRoot">
<TextBlock TextWrapping="Wrap" Text="{Binding MyName, ElementName=LayoutRoot}"/>
</Grid>
Custom UserControl Code:
public static readonly DependencyProperty TextBoxTextProperty =DependencyProperty.Register("TextBoxText", typeof(string), typeof(UserControl1));
public string TextBoxText
{
get { return (string)GetValue(TextBoxTextProperty); }
set { SetValue(TextBoxTextProperty, value); }
}
In my Main Window XAML :
<Grid x:Name="LayoutRoot">
<Button Content="Button" Height="78" Margin="0,0,93,112" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="94" Click="MyButtonClick"/>
<ListBox x:Name="MyListBox" HorizontalAlignment="Left" Margin="8,8,0,112" Width="192">
<ListBox.ItemTemplate>
<DataTemplate>
<local:UserControl1 HorizontalAlignment="Stretch" Margin="286,37,56,0" VerticalAlignment="Top" d:LayoutOverrides="Height" TextBoxText="{Binding MyName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
In my Main Window Code :
private void MyButtonClick(object sender, System.Windows.RoutedEventArgs e)
{
List<string> MyName = new List<string>();
MyName.Add("Name 1");
MyName.Add("Name 2");
MyName.Add("Name 3");
MyListBox.ItemsSource = MyName;
}
This Code Successfully add my Custom UserControl as ListBoxItem in ListBox But Problem it is not display any text which i Binding.
I don`t understand where i am doing wrong.
You set the DataContext of the UserControl to itself, all bindings will then try to find the path on the UserControl, that is why you should not set the DataContext on UserControls.
You should see a binding error in the Output window of Visual Studio saying something like:
System.Windows.Data Error: 40 : BindingExpression path error: 'ItemTypeIdCode' property not found on 'object' ''UserControl1' (Name='UserControl')'. ...

Categories