Reputation: 900
I would like to ask if there is something like ObservableCollection but for object in WPF C#.
Here is my problem:
I have following Grid
in XAML:
<Grid x:Name="detailsGrid">
<TextBox Text="{Binding Name, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" />
<TextBox Text="{Binding Excerpt, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" />
</Grid>
In my code behind I set the DataContext of detailsGrid
to object of following class:
recipeDetails = new RecipeDetailsContainer();
this.detailsGrid.DataContext = recipeDetails;
RecipeDetailsContainer
class:
public class RecipeDetailsContainer : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged("Name");
}
}
private string _excerpt;
public string Excerpt
{
get { return _excerpt; }
set
{
_excerpt = value;
NotifyPropertyChanged("Excerpt");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
In other class method I want to write this info to WPF window, so I set:
private void PrintInfoAboutRecipe(object sender, RecipeHandlerArgs e)
{
this.Dispatcher.Invoke((Action)(() =>
{
if (e.Container != null && e.Container.Recipe != null)
{
this.recipeDetails.Name = e.Container.Recipe.Name;
this.recipeDetails.Excerpt = e.Container.Recipe.Excerpt;
}
else
{
this.recipeDetails.Name = "";
this.recipeDetails.Excerpt = "";
}
}));
}
But my binding does not work and nothing is showed in TextBlocks.
Am I doing something wrong? Any help would be appreciated. Thanks! :-)
Upvotes: 0
Views: 144
Reputation: 1076
<Grid x:Name="detailsGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Name}" />
<TextBox Grid.Column="1" Text="{Binding Excerpt}" />
</Grid>
Try to add your TextBoxes in Columns, because they are at same place. Second try to initialize your properties in the class constructor.
public class RecipeDetailsContainer : INotifyPropertyChanged
{
public RecipeDetailsContainer() {
Name = string.Empty;
Excerpt = string.Empty;
}
Further Information about BindingMode can be found here:
Dispatcher
It could be that you have to Dispatcher.Current.Invoke()
the sets of your Properties. If you set them from a different thread the binding Fails.
Upvotes: 1
Reputation: 2902
Assuming datacontext, vm etc is correct:
Xaml:
<Grid>
<Grid.RowDefinitons>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <!-- empty space, not sure how you want your gui
but your boxes would overlap in your example -->
</Grid.RowDefinitions>
<!-- updates binding on vm/datacontext on each keypress -->
<TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<!-- updates binding on vm/datacontext when focus is lost -->
<TextBox Grid.Row="1" Text="{Binding Excerpt, Mode=TwoWay" />
</Grid>
The UpdateSourceTrigger=PropertyChanged is a bit paranoid, the default is the the binding updates your viewmodel once the text box looses behaviour. From the little I know from your example I would dropped it. The two way binding is important in control where you want to both be able to update a Property/DP, both from the GUI and the VM.
You have somtething called the WPF cheatsheet, it's old but there you have most you need about bindings in one very compact place. When learning WPF I had document stuck to the wall behind my computer @ work, home & school when learning WPF.
Hope it helps,
Cheers,
Stian
Upvotes: 1