Category Archives: WPF

ObservableCollection vs. List. DataBinding – Which one to use when?

Would it be enough to track changes to objects already in the list? Or do you need to know when objects are removed from/are added to/change positions within the list?

If a list will contain the same items for their whole lifetime, but the individual objects within that list will change, then it’s enough for just the objects to raise change notifications (typically through INotifyPropertyChanged) and List<T> is sufficient. But if the list will contain different objects from time to time, or if the order changes, then you should use ObservableCollection<T>.

Advertisements

Access parent object data context

Say if i have a Textbox inside a canvas control and canvas datacontext is set to address object on view model. Now this textbox will by default inherit and correspond to the attributes of this address object in view model. So if this address object has properties like AddressLine1, Street, City etc then i can use any of these to set my textbox text.

But what If i need to go one level up to parent data context and get the name of the main customer object which is bound to the window(or for any matter any parent control) then i can do this:

Binding=”{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FirstName}

Get compile time support for Property names

Hello,

Many times we need to use string values for C# properties. Although this is not a common practise, we may not have choice sometimes e.g. using RX –

Observable.FromEventPattern<PropertyChangedEventArgs>(this,"PropertyChanged")
 .Where(e => e.EventArgs.PropertyName == "SearchString")
 .Subscribe(_ => DoSomeWork());

In this case,  we have to pass the string value (name) of the property for RX Observable to work. I am interested in subscribing to this event of my property(which is in turn bound to textbox on view).

So I can either pass the string literal which provides no compile time support or I can use expression trees to pass an expression and retrieve string name literal at runtime as follows:

Observable.FromEventPattern<PropertyChangedEventArgs>(this,"PropertyChanged")
 .Where(e => e.EventArgs.PropertyName == GetPropertyName(() => SearchString))
 .Subscribe(_ => DoSomeWork());

This works because I have written a private function in my class to extract the actual string name from the propertyname. The function is as follows:

public static string GetPropertyName<T>(Expression<Func<T>> expression)
{
    MemberExpression memberExpression = (MemberExpression)expression.Body;
    return memberExpression.Member.Name;
}

Have a nice day!

Anything defined inside ResourceDictionary must be available as static resource

My VS has some issued which was driving me crazy. I declared a resource (an object) in a resource dictionary and gave it a key. This resource dictionary was external and was referenced via MergedDictionaries. When i tried referencing that resource via its key, I was getting compile time error saying resource not found. This could lead to a lot of confusion for beginners. Please note that whether you define the resource inline, or at parent container(i.e grid/stackpanel etc) or at usercontrol/windows level or even at Application level, it must be available to be referenced in a consistent manner irrespective of its scope and definition

e.g.

<Window x:Class="WpfApplication1.MainWindow"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 x:Name="Window"
 Title="MainWindow" Height="677" Width="686.194">
 <Grid x:Name="Grid">
 <Grid.Resources>
 <ResourceDictionary>
 <ResourceDictionary.MergedDictionaries>
 <ResourceDictionary Source="Dictionary1.xaml"></ResourceDictionary>
 </ResourceDictionary.MergedDictionaries>
 </ResourceDictionary>
 </Grid.Resources>

 <ListBox Name="ItemsControl" ItemsSource="{Binding ElementName=Window, Path=Collection}" ItemTemplateSelector="{StaticResource ViewTemplateSelector}" Margin="0,0,328,0"/>
 <Button Content="Open View One" HorizontalAlignment="Left" Margin="450,73,0,0" VerticalAlignment="Top" Width="95" Click="Button_Click"/>
 <Button Content="Open View Two" HorizontalAlignment="Left" Margin="450,145,0,0" VerticalAlignment="Top" Width="95" Click="Button_Click_1"/>
 </Grid>
</Window>

 

The above code refereneces a ViewTemplateSelector resource which is defined in an external dictionary called Dictionary1.xaml. Now even if this resource is moved to App.xaml or inline within the window itself, i shouldn’t need to have to change my {StaticResource ViewTemplateSelector} markup at all

I sorted the bug in my VS but I thought if the same happens to a novice WPF learner the it might change his fundamental understanding on how resources are referenced.

Working with DataTemplateSelector

Hello,

When you are working with DataTemplateSelector, make sure that you call the InitialiseComponent() method at the end of the constructor in codebehind.  Have a look at the following code:

 public partial class MainWindow : Window
 {
 public MainWindow()
 {
 

 Collection = new ObservableCollection<INotifyPropertyChanged>();
 Collection.Add(new ViewModel1());
 Collection.Add(new ViewModel2());
 Collection.Add(new ViewModel1());
 Collection.Add(new ViewModel2());
 Collection.Add(new ViewModel1());
 Collection.Add(new ViewModel2());

 InitializeComponent();  //Don't put this as 1st line

 }


 public ObservableCollection<INotifyPropertyChanged> Collection { get; set; }
 
 }

If I just move the call to InitialiseComponent() at the begining of the constructor as the first statement, i don’t get any runtime errors or even any exception on output window but my view renders blank. The main cause being that the binding is already done before InitialiseComponent() and if i set the Collection property after that, it doesn’t do anything because the opportunity has passed.

My Collection property is bound to an ItemsControls in XAML and this ItemsControl uses an ItemTemplateSelector to select the correct DataTemplate for the showing the view.

 

Be careful with Data Template markup

This one is rather for WPF beginners but even after working on WPF for few years, I happened to make this mistake and overlooked it. So just wanted to highlight it for benefit of others…..

When you define a DataTemplate, make sure that you define the x:Key attribute before any other attributes, otherwise it will not get picked up because of the ForwardOnly usage policy of static resource.  I tried the following:

<DataTemplate DataType="wpfApplication1:ViewModel1" x:Key="DataTemplate1" >
 <wpfApplication1:View1/>
 </DataTemplate>

and it gave me the famous error:  “Cannot find resource named ‘DataTemplate2’. Resource names are case sensitive.”

Just by changing the order of the x:Key attribute and putting it before DataType attribute, solved this error. So be careful 🙂

Have a nice day!

.net crosses over the net

On Wednesday, Microsoft Corp. reinforced its commitment to cross-platform developer experiences by open sourcing the full server-side .NET stack and expanding .NET to run on the Linux and Mac OS platforms. Microsoft also released Visual Studio Community 2013, a new free edition of Visual Studio that provides easy access to the Visual Studio core toolset. The announcements kicked off Microsoft’s Connect (); event, where the company released Visual Studio 2015 Preview and .NET 2015 Preview.

“With billions of devices in the market today, developers need tools that target many different form factors and platforms,” said S. Somasegar, corporate vice president, Developer Division, Microsoft. “Through Visual Studio and .NET we are committed to delivering a comprehensive end-to-end solution for developers to build and manage applications across multiple devices and platforms.”

For more information visit here:  .net goes open source