WPF data binding issue - wpf

I am just new to WPF.
I have a wpf app and there i simply have a dock panel and inside dock panel i have a textblock.
I want to bind the text property of textblock to my custom object's property but that' not working.
I think i am missing something here but don't know what.
Here is the code snippet.
<TextBlock Text="{Binding Source=myDataSource, Path=ColorName}"/>
</DockPanel>
My custom class.
class MyData
{
public string ColorName { get; set; }
}
and main window constructor..
public partial class MainWindow : Window
{
MyData myDataSource;
public MainWindow()
{
InitializeComponent();
myDataSource = new MyData { ColorName = "Red" };
}
}

myDataSource needs a get and set. You also need to set the dataContext for the window, so it should be-
public partial class MainWindow : Window
{
public MyData MyDataSource { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
MyDataSource = new MyData { ColorName = "Red" };
}
}
public class MyData
{
public string ColorName { get; set; }
}
and xaml code should be -
<TextBlock Text="{Binding MyDataSource.ColorName}"/>
edit Sorry got this wrong I've changed to the correct code

What you bind to needs to be a
public property. (Your data-object needs to satisfy that condition as well)
Unless you set the property before
InitializeComponent() the binding
will might not update depending on your binding.
If you set it again at any point in
time after the initilization and want the binding to be updated you
should implement
INotifyPropertyChanged or work
with dependency properties.
Since the data is in your window you might need to access it over that:
{Binding ElementName=window, Path=myDataSource.ColorName}

If you only want to bind to MyData, don't set window as its own DataContext. Istead, set the data you're binding to. This way it's more clear what is data, and what is view.
Also, lose the Source on Binding, you won't generally need it.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyData { ColorName = "Red" };
}
}
public class MyData
{
public string ColorName { get; set; }
}
XAML:
<TextBlock Text="{Binding ColorName}"/>

Related

WPF binding static list to combobox

Trying to understand how to bind this static list to a combobox that located on different window.
public partial class MainWindow : Window
{
public static List<Classes.Entity> EntityList { get; set; }
public MainWindow()
{
EntityList = new List<Classes.Entity>();
InitializeComponent();
}
...
the object:
public class Entity
{
public string entityName { get; set; }
...
XAML (In a diffrent window, call "NewRelationship.xaml.cs"
<ComboBox x:Name="cb_from" ItemsSource="{Binding Path=EntityList}" DisplayMemberPath="entityName" SelectedValue="{Binding Path=Entity}" />
Of course I fill the list later in the code...
if I moving the list to the newRelationship window and add "this.datacontext = this;" its working,
How do I make this work when the list is in the mainWindow? Thanks...
A better approach would be to keep the EntityList in a separate object that both windows could reference:
class ViewModel
{
private List<Classes.Entity> _entityList = new List<Classes.Entity>();
public IEnumerable<Classes.Entity> EntityList
{
get { return _entityList; }
}
}
partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
When the second window is created, you can pass an instance of the ViewModel class to it, and set it as the DataContext.

How do I bind DateTime as DepedencyProperty of a DependencyObject so that it will show up in a textbox?

I want to learn how to use Dependency Objects and Properties. I have created this class,
public class TestDependency : DependencyObject
{
public static readonly DependencyProperty TestDateTimeProperty =
DependencyProperty.Register("TestDateTime",
typeof(DateTime),
typeof(TestDependency),
new PropertyMetadata(DateTime.Now));
public DateTime TestDateTime
{
get { return (DateTime) GetValue(TestDateTimeProperty); }
set { SetValue(TestDateTimeProperty, value); }
}
}
The window class is like this
public partial class MainWindow : Window
{
private TestDependency td;
public MainWindow()
{
InitializeComponent();
td = new TestDependency();
td.TestDateTime = DateTime.Now;
}
}
Now I want to use it to show a the current DateTime in the TextBlock which updates itself every second, by adding this to a grid
<Grid>
<TextBlock Text="{Binding TestDateTime,ElementName=td}" Width="200" Height="200"/>
</Grid>
I can see the TextBlock, but there is no Date Time value in it at all. What am I doing wrong?
First of all if you want to update the display time once a second your going to need a timer to trigger an update. A DispatchTimer works works well for that.
public class TestDependency : DependencyObject
{
public static readonly DependencyProperty TestDateTimeProperty =
DependencyProperty.Register("TestDateTime", typeof(DateTime), typeof(TestDependency),
new PropertyMetadata(DateTime.Now));
DispatcherTimer timer;
public TestDependency()
{
timer = new DispatcherTimer(new TimeSpan(0,0,1), DispatcherPriority.DataBind, new EventHandler(Callback), Application.Current.Dispatcher);
timer.Start();
}
public DateTime TestDateTime
{
get { return (DateTime)GetValue(TestDateTimeProperty); }
set { SetValue(TestDateTimeProperty, value); }
}
private void Callback(object ignore, EventArgs ex)
{
TestDateTime = DateTime.Now;
}
}
Next we need to modify the XAML so it binds properly to the updated dependency object.
<Window.DataContext>
<local:TestDependency/>
</Window.DataContext>
<Grid>
<TextBlock Text="{Binding TestDateTime}" />
</Grid>
Since we set the DataContext in XAML you can actually delete all of the code behind code in the MainWindow constructor.
If you just want to show some values in your TextBlock, you don't need a Dependency Object here. Try something like this:
public partial class MainWindow : Window
{
public DateTime Test
{ get; set; }
public MainWindow()
{
InitializeComponent();
this.Test = DateTime.Now;
}
}
<Grid>
<TextBlock Text="{Binding Path=Test,RelativeSource={RelativeSource AncestorType=Window,Mode=FindAncestor}}"></TextBlock>
</Grid>
Here I am not showing the code which can update the value every second. I just want to clarify that this is not the right situation to use Dependency Property.
Of course you can use Dependency Property to do this. But Dependency Object and Dependency Property can offer you some extension functionality such as Data Binding. But it doesn't mean that you need to use a Dependency Object or Dependency Property as the source of the Data Binding.

Simple Windows Phone User Control Databinding Does Not Work

I have an issue with something that should be very simple databinding scenario. I want to bind a list of items. I want to create a user control put it in a ItemsControl's template and bind the ItemsControl to some data. I am perfectly happy with one time databinding so I was kind of hoping to avoid learning about dependency properties and all the databinding stuff for this simple scenario.
Here is the XAML for the user control:
<TextBlock>Just Something</TextBlock>
And the code behind:
namespace TestWindowsPhoneApplication
{
public partial class TestControl : UserControl
{
public TestData SomeProperty { get; set; }
public String SomeStringProperty { get; set; }
public TestControl()
{
InitializeComponent();
}
}
}
MainPage.xaml:
<ItemsControl Name="itemsList" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<t:TestControl SomeStringProperty="{Binding Path=SomeString}"></t:TestControl>
<!--<TextBlock Text="{Binding Path=SomeString}"></TextBlock>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here is MainPage.xaml.cs:
namespace TestWindowsPhoneApplication
{
public class TestData
{
public string SomeString { get; set; }
}
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
itemsList.DataContext = new TestData[] { new TestData { SomeString = "Test1" }, new TestData { SomeString = "Test2" } };
}
}
}
When I run the project I get an error "the parameter is incorrect". I also tried binding directly to the item with SomeProperty={Binding} since that is what I actually want to do but this causes the same error. If I try doing the same thing with the TextBlock control (the commented line) everything works fine.
How can I implement this simple scenario?
To make a property on your custom control "bindable" you have to make it a dependency property. Check out my answer here for a nice simple example of doing just this on a custom control: passing a gridview selected item value to a different ViewModel of different Usercontrol
public string SomeString
{
get { return (string)GetValue(SomeStringProperty); }
set { SetValue(SomeStringProperty, value); }
}
public static readonly DependencyProperty SomeStringProperty =
DependencyProperty.Register("SomeString", typeof(string), typeof(TestControl),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnSomeStringChanged)));
private static void OnSomeStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((TestControl)d).OnSomeStringChanged(e);
}
protected virtual void OnSomeStringChanged(DependencyPropertyChangedEventArgs e)
{
//here you can do whatever you'd like with the updated value of SomeString
string updatedSomeStringValue = e.NewValue;
}

bind a control to a code-behind property of this object

I have a property in a code-behind class to which I want to bind my Label control:
public MainWindow()
{
InitializeComponent();
this.Label1Content = "some text";
}
public string Label1Content { get; set; }
But the binding fails. Obviously I am missing something in the binding configuration, but I don't know what. I know how to bind this property using C#, but how do I bind it using XAML and without declaring DataContext?
If you don't want to declare a datacontext anywhere, you could use
<Label Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=Label1Content}" />
You still have to declare a DataContext, even if it is the same control:
public MainWindow()
{
InitializeComponent();
DataContext = this;
this.Label1Content = "some text";
}
Also, the control will have to implement INotifyPropertyChanged so you can raise the PropertyChanged event. You're property should be self-contained like so:
public string _lable1Content;
public string Label1Content
{
get { return _label1Content; }
set
{
if (Equals(value, _label1Content)) return;
_label1Content = value;
//However you decide to implement the RaisePropertyChanged method.
}
}

Simple WPF data binding

I want to separate my user interface from my code, so I (obviously) landed at bindings. As a test, I've written the following XAML:
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="Auto" Width="200">
<StackPanel>
<TextBox Text="{Binding Item}"/>
<Button Content="Add" Click="AddNew"/>
<ListBox Height="100" ItemsSource="{Binding Items}"/>
</StackPanel>
</Window>
The C# looks like this:
namespace BindingTest
{
public partial class MainWindow : Window
{
public string Item { get; set; }
public ObservableCollection<string> Items { get; set; }
public MainWindow()
{
InitializeComponent();
Items = new ObservableCollection<string>();
}
private void AddNew(object sender, RoutedEventArgs e)
{
Items.Add(Item);
}
}
}
What I want to happen is that the text entered into the textbox is added to the listbox's itemssource. However, this doesn't happen...
Two things you need two do -
Set - DataContext = this; in your constructor.
You'd be better off if you would change your properties to dependency properties instead. You could do that easily with the "propdp" snippet in visual studio.
Data binding is performed against the current data context. However, you have not set the data context for your window. Often you will set the data context to a view model but in your case you simply want to use the window class for that.
You should add the following line to the constructor:
DataContext = this;
Change your code to this:
public partial class MainWindow : Window
{
public string Item { get; set; }
public ObservableCollection<string> Items { get; set; }
public MainWindow()
{
InitializeComponent();
Items = new ObservableCollection<string>();
DataContext = this;
}
private void AddNew(object sender, RoutedEventArgs e)
{
Items.Add(Item);
}
}
}
You do need to set your DataContext - works for me.
Two things:
You should set the correct data context for your window. Otherwise the binding will not find your properties.
You should initialize your Items collection before the InitializeComponent() call as inside it the ListBox tries to evaluate the expression and get NULL as the binding souce. And since you are not implementing INotifyPropertyChanged and the property is not a DependencyProperty the ListBox will never reevaluate the binding thus it will never get the instance of your Items collection.
So, the code should be as follows:
public MainWindow()
{
Items = new ObservableCollection<string>();
DataContext = this;
InitializeComponent();
}
Try this
hope this will work. But this is not hte right approach. You need to set the DataContext to the Object whose properties u guna use for binding. you must follow MVVM Architecture.

Resources