Showing posts with label Databinding. Show all posts
Showing posts with label Databinding. Show all posts

Thursday, July 3, 2014

Binding Viewmodel property to tabitem header in MVVm pattern

Its been a while since I started a WPF project from scratch. I was mainly into the architectural side of application rather than UI side. Today I got an opportunity to start one app. It is supposed to be simple WPF application where the screens are arranged in hierarchical tabs.

The application is supposed to be a temporary application which will be used to test an algorithm developed by the business before its getting integrated into the actual application. So thought of not following the MVVm pattern as its supposed to be developed from our offshore in less amount of time. But one discussion with my lead architect changed my decision. If we are doing something we should do it right. We don't know whether the client will get rid of the application if it feels too good for them. Finally decided to go with MVVm.

The initial decision I had to take about the MVVm infrastructure. Earlier when I used to start the project I take my own RelayCommand,ViewmodelBase classes. That was the beginning time of WPF. But this time I decided to use a good library on the assumption that the MVVm framework must be matured by now. It ends up in using MVVM Light. Its a nice library which we can get from nuget.

Then started thinking about the UI structure where the tabs needs to be shown in hierarchical way. Its nothing but there will be one parent level tab control and in every tab page there will be one more tab control. I created the view models and bound to the view. Each high level view model have ChildVMs collection. In the MainPage.xaml UI I was able to bound to the ChildVMs property and they showed up as each and every viewmodel was associated with data template.

    <Application.Resources>
        <DataTemplate DataType="{x:Type vms:ChildViewmodel_1}">
            <vws:ChildViewUserControl_1/>
        </DataTemplate>
    </Application.Resources>

But I faced one problem. I could see that the tab headers are also showing the same control which is inside the tab page. Ideally I need to edit the tab header template and bind to the header property in the viewmodel. But I could see one more way which is just a data template for the tab item.

        <TabControl ItemsSource="{Binding ChildVMs}">
            <TabControl.ItemTemplate>
               
                <DataTemplate>
                    
                    <TextBlock Text="{Binding Header}" />
                </DataTemplate>
            </TabControl.ItemTemplate>
        </TabControl>

Happy coding

Sunday, March 20, 2011

Open source WPFInspector

Another Snoop like debugging tool for WPF.But this is useful to debug and inspect DataContext,Resources,Triggers & Styles.

I don’t want to compare this with Snoop.Check it out yourself !!!

http://wpfinspector.codeplex.com

Saturday, August 7, 2010

Debugging WPF and Silverlight DataBinding

Good article about debugging data binding in WPF and silverlight.

http://blogs.msdn.com/b/wpfsldesigner/archive/2010/06/30/debugging-data-bindings-in-a-wpf-or-silverlight-application.aspx

In short we can debug databinding in 2 ways

  1. Looking at the output/immediate window.
  2. Using converters.
  3. Putting break points in get and set regions of properties

Saturday, May 16, 2009

MVVM CommandReference and KeyBinding

Recently when I was digging into MVVM sample in codeplex I came to notice one class named CommandReference.That class just contains a dependency property which is of ICommand.At first, I didn’t get why they created that class.But after seeing it’s application in the sample,I decided to add that in my MVVM.Core project because that was important when we come to a situation where  we need to bind a command to non dependency properties.Eg :InputBinding.Command
If you still didn’t get the importance of CommandReference just try to Bind a command to a KeyBinding as follows.

<Window.InputBindings>
<KeyBinding Modifiers="Control"
Key="N"
Command="{Binding CreateCustomerCommand}" />
</Window.InputBindings>


The result will be an Exception



A 'Binding' cannot be set on the 'Command' property of type 'KeyBinding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject



Reason is simple the Command property is not DependencyProperty.To get rid of this we have to use the CommandReference.The usage is as follows.



<Window.Resources>
<coreView:CommandReference x:Key="newCust"
Command="{Binding NewCustomerCommand}" />
</Window.Resources>
<Window.InputBindings>
<KeyBinding Modifiers="Control"
Key="N"
Command="{StaticResource newCust}" />
</Window.InputBindings>

See the sample for more details.This is again a modified version of Josh Smith's MVVM sample.

Tuesday, March 31, 2009

DataBinding to App.Settings values

.Net 2.0 introduced this feature which helps to store and retrieve application specific settings very easily.You can easily create Settings through the visual editor.If we want to access them in code we can just use the Properties.Settings.Default object directly.The Default object will have all the properties which we had created at design time.
Showing ConnectionString entry in Messagebox
MessageBox.Show(Properties.Settings.Default.ConnectionString);


It is very easy.Lets learn how this can be binded in to a WPF TextBox.

First make a namespace reference to the Properties namespace.If your application name is WpfApplication1 it is xmlns:props=”WpfApplication1.Properties”.

Then in the Binding set source as the Default property available in the class Settings.Since it is static you have to use the x:Static binding extension.

Finally the path is ConnectionString which is the settings entry name.

Putting it altogether.


<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.Window1"
x:Name="Window"
xmlns:props="clr-namespace:WpfApplication1.Properties">
<Grid x:Name="LayoutRoot">
<TextBox  HorizontalAlignment="Left"  VerticalAlignment="Top"
Text="{Binding Source={x:Static props:Settings.Default},Path=ConnectionString}">
</TextBox>
</Grid>
</Window>


So enjoy WPF data binding to Properties.Settings.Default.

Monday, March 16, 2009

ObservableDictionary

The existing Dictionary is not a friend of WPF in the case of databinding.ie WPF can't listen on it's CollectionChanged and hence the UI won't get updated if you add or remove anything to or from the dictionary.
What I was doing is to create a new class with 2 properties (Key and Value) and it's Collection class derived from ObservableCollection.

For example in a card game, if we want to store the 'Play' keyed by Player object (like Dictionary<player,card>),we have to create a class PlayCard which have Player and Card properties and it's collection class PlayCardCollection derived from ObservableCollection.

This is very much time consuming.Here Dr.WPF has provided one implementation of ObservableDictionary which has the capabilities to provide CollectionChanged.Now it is very easy to have ObservableDictionary<player,card>.
Thanks to Dr.WPF for such a great work.

Thursday, February 5, 2009

WPF Databinding sheet

If you can't remember all the formats of databinding just have a look here
http://www.nbdtech.com/Free/WpfBinding.pdf

Saturday, December 13, 2008

Creating custom wpf markup extension to show class fields

Here is one link which describes what is markup extension and available markup extensions.
Markup extensions are very much useful to obtain a clean project.Things won't get mixed with each other.Xaml itself contains the lines which have the functionality.

Consider the scenario where we need to display all properties of given class in a listbox.We normally write C# or VB code to get PropertyInfo objects and return the same.This code normally resides in presentation files itself.

Here comes the need for markup extension.We can write our own extension by inheriting from the MarkUpExtension class.

Steps to Create a custom markup extension

  1. Create a class which derives from MarkupExtension.The naming convention is that the class name should ends with 'Extension' .Eg:TypeDescriptorExtension
  2. If we need to accept a default parameter with extension write a constructor
  3. Add other properties as well.
  4. Override ProvideValue Method and return the appropriate value after processing.

Eg: Creating custom markup extension to list Properties and methods of a Class

The PropertyDescriptorExtension class is derived from Markupextension and it accepts an object Type as default parameter.So the constructor is written with a parameter of type 'Type'.

public class TypeDescriptorExtension:MarkupExtension
{
public TypeDescriptorExtension( Type type):this()
{
Type = type;
}
}

The other properties are IncludeProperties and InCludeMethods which are boolean to indicate whether the out put list should include Properties and Methods respectively.IncludeProperties is true by default.

Now override the ProvideValue method.Get the properties and methods collection based on the properties using Reflection and return as well.

public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Type == null)
{
throw new InvalidOperationException("The Class must be specified.");
}
List<string> items = new List<string>();

if (IncludeProperties)
{
foreach (PropertyInfo item in Type.GetProperties())
{
items.Add(item.ToString());
}
}
if (IncludeMethods)
{
foreach (MethodInfo info in Type.GetMethods())
{
items.Add(info.ToString());
}
}
return items;
}

Using the TypeDescriptorExtension
Normal, which displays only properties

 <ListBox ItemsSource="{Binding Source={local:TypeDescriptor {x:Type Button}}}" />
Displays methods only
 <ListBox ItemsSource="{Binding Source={local:TypeDescriptor {x:Type Button},IncludeMethods=True,IncludeProperties=False}}" />

Sample is available here.

Monday, July 2, 2007

Simple filtering in ListBox / CollectionView

The following code snippet will allow you to filter out unwanted items from your collection.

<Grid Name ="grd">
<Grid.Resources>
<XmlDataProvider x:Key="Company" XPath="/Company">
<x:XData>
<Company xmlns="">
<Person Name="Jack" Role="CEO"/>
<Person Name="Tim" Role="PL" />
<Person Name="Jil" Role="PL" />
<Person Name="Jimmy" Role="PM" />
<Person Name="Joy" Role="PM" />
<Person Name="Jim" Role="PL" />
<Person Name="Jack" Role="PM" />
</Company>
</x:XData>
</XmlDataProvider>
<DataTemplate x:Key="template">
<TextBlock Text="{Binding XPath=@Name}"/>
</DataTemplate>
<CollectionViewSource x:Key="cvs" Source="{Binding Source={StaticResource Company},XPath=Person}"
Filter="src1_Filter"/>
</Grid.Resources>
<ListBox Name="lst"
ItemTemplate="{StaticResource template}"
ItemsSource="{Binding Source={StaticResource cvs}}"/>
</Grid>

//Filter method
void src1_Filter(object sender, FilterEventArgs e)
{
System.Xml.XmlElement ele=e.Item as System.Xml.XmlElement;
string name=ele.Attributes[0].Value ;
if (name == "Tim") e.Accepted = true;
else e.Accepted = false;
}

This will display item "Tim".You may do custom filtering as you like in the filter method

Friday, June 29, 2007

Simple grouping in ListBox





<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="Company" XPath="/Company">
<x:XData>
<Company xmlns="">
<Person Name="Jack" Role="CEO"/>
<Person Name="Tim" Role="PL" />
<Person Name="Jil" Role="PL" />
<Person Name="Jimmy" Role="PM" />
<Person Name="Joy" Role="PM" />
<Person Name="Jim" Role="PL" />
<Person Name="Jack" Role="PM" />
</Company>
</x:XData>
</XmlDataProvider>

<DataTemplate x:Key="categoryTemplate">
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Background="ForestGreen" Margin="0,5,0,0"/>
</DataTemplate>
<DataTemplate x:Key="template">
<TextBlock Text="{Binding XPath=@Name}"/>
</DataTemplate>

<CollectionViewSource x:Key="cvs" Source="{Binding Source={StaticResource Company},XPath=Person}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="@Role"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Grid.Resources>


<ListBox Name="lst"
ItemTemplate="{StaticResource template}"
ItemsSource="{Binding Source={StaticResource cvs}}">
<ListBox.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource categoryTemplate}" />
</ListBox.GroupStyle>
</ListBox>
</Grid>

If you want to sort items in these groups please use SortDescriptions along with GroupDescriptions.For more details visit
http://www.beacosta.com/2006/01/how-do-i-sort-groups-of-data-items.html

Wednesday, June 27, 2007

Hierarchical databinding into TreeView



<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="Company" XPath="*">
<x:XData>
<Reporting xmlns="">
<Person Name="CEO">
<Person Name="GM" >
<Person Name="PM-1" />
<Person Name="PM-2" >
<Person Name="PL" />
</Person >
<Person Name="PM-3" />
<Person Name="PM-4">
<Person Name="PL-2" />
<Person Name="PL-3" />
</Person>
<Person Name="PM-5" />
</Person>
</Person>
</Reporting>
</x:XData>
</XmlDataProvider>
<HierarchicalDataTemplate DataType="Person" ItemsSource ="{Binding XPath=*}">
<TextBlock Text="{Binding XPath=@Name}" />
</HierarchicalDataTemplate>

</Grid.Resources>
<TreeView ItemsSource="{Binding Source={StaticResource Company}, XPath=*}"/>
</Grid>