יום ראשון, 17 באפריל 2011

WPF - Custom Command Binding



XAML:
<UserControl.CommandBindings>
   // Command Binding
      <CommandBinding Command="Save" 
                      CanExecute="SaveCanExecute" 
                      Executed="SaveExecuted">            
      </CommandBinding>
// Custom Command Binding
      <CommandBinding Command="{x:Static local:WorkOrderDetailsTreeViewModel._SetEditorFocus}" 
                     Executed="_SetEditorFocusExecuted"/>
      </UserControl.CommandBindings>


In Code Behind:
public static RoutedCommand _SetEditorFocus = new RoutedCommand();
public ConstructoyOfTheClass()
{
_SetEditorFocus.InputGestures.Add(new KeyGesture(Key.F5, ModifierKeys.None));
}



WPF - Command Binding


Example how to Create CommandBindingin in WPF:
Command Binding in WPF working like Bubbles and will stop
only if: e.Handled = true, if e.Handled = false Command will continue finding all VisualTree untill root element.
XAML:
<UserControl.CommandBindings>
  <CommandBinding Command="Save" 
                  CanExecute="SaveCanExecute" 
                 Executed="SaveExecuted">            
  </CommandBinding>
  <CommandBinding Command="{x:Static local:WorkOrderDetailsTreeViewModel._SetEditorFocus}" 
                  Executed="_SetEditorFocusExecuted"/>
</UserControl.CommandBindings>


C#:
private void SaveCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }
 
        private void SaveExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            //TODO;
        }        



WPF - Manually Update Binding Source


When we use binding, we can couple of ways of data binding: 

* OneWay
* Two Way
* OneWayToSource
OneTime


And, there are several UpdateSourceTriggers:

* LostFocus
* PropertyChanged
* Explicit

You can find all details information here: http://msdn.microsoft.com/en-us/library/ms752347.aspx#basic_data_binding_concepts

XAML for example:

<ComboBox Name="comboHour" ItemStringFormat="HH:mm" 
                           SelectedValue="{Binding EnteredOnTime, 
                                           Mode=TwoWay, 
                                           UpdateSourceTrigger=Explicit}" 
                           Background="#0E0000FF"  
                           Width="70" 
                           HorizontalAlignment="Left"/>



public static void UpdateItemSource(FrameworkElement item)
        {
            FieldInfo[] infos = item.GetType().GetFields(BindingFlags.Public | BindingFlags.Fl            attenHierarchy | BindingFlags.Instance | BindingFlags.Static);
            foreach (FieldInfo field in infos)
            {
                if (field.FieldType == typeof(DependencyProperty))
                {
                    DependencyProperty dp = (DependencyProperty)field.GetValue(null);
                    BindingExpression ex = item.GetBindingExpression(dp);
                    if (ex != null)
                    {                        
                      if(ex.ParentBinding.UpdateSourceTrigger == UpdateSourceTrigger.Explicit)
                         ex.UpdateSource();
                    }
                }
            }
          
            int count = VisualTreeHelper.GetChildrenCount( item);
            for (int i = 0; i < count; i++)
            {
              FrameworkElement child = VisualTreeHelper.GetChild(item, i) as FrameworkElement;
                if(child != null)
                    UpdateItemSource(child);
            }
        }    

יום רביעי, 13 באפריל 2011

WPF - VisualTreeHelper - FindChild / FindParent Methods Examples

Find Child:

private DependencyObject FindChildControl<T>(DependencyObject control)
{
  int childNumber = VisualTreeHelper.GetChildrenCount(control);
  for (int i = 0; i < childNumber; i++)
  {
    DependencyObject child = VisualTreeHelper.GetChild(control, i);
    if (child != null && child is T)
        return child;
    else
        FindChildControl<T>(child);                
  }
  return null;
}
Find Parent:
private DependencyObject FindParentControl<T>(DependencyObject control)
{
   DependencyObject parent = VisualTreeHelper.GetParent(control);
   while (parent != null && !(parent is T))
   {
       parent = VisualTreeHelper.GetParent(parent);
   }        
   return parent;
}
Enjoy ! 

יום שני, 11 באפריל 2011

WPF - ObservableCollection via BindingList



Very important question, witch data structure to use when we working with WPF  ObservableCollection or BindingList?

1.      The practical difference is that BindingList is for WinForms, and ObservableCollection is for WPF.
From a WPF perspective, BindingList isnt properly supported, and you would never really use it in a WPF project unless you really had to.

but...

2.      ObservableCollection implements INotifyCollectionChanged which provides notification when the collection is changed (you guessed ^^) It allows the binding engine to update the UI when the ObservableCollection is updated.
However, BindingList implements IBindingList.
IBindingList provides notification on collection changes, but not only this. It provides a whole bunch of functionality which can be used by the UI to provides a lot more thing than only UI updates according to changes, like:
·         Sorting
·         Searching
·         Add through factory (AddNew member function).
·         Readonly list (CanEdit property)
All these functionalities are not available in ObservableCollection
Note that in Silverlight, BindingList is not available as an option: You can however use ObservableCollections and ICollectionView (and IPagedCollectionView if I remember well).

The choice is yours :-)

Thanks.

יום ראשון, 10 באפריל 2011

WPF - Set


Just example of creating Style for specific Control Type, 
but with very IMPORTANT tip:

Don't specify x:Key value - it's doesn't work:

<UserControl.Resources>
        <Style TargetType="{x:Type Label}">
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="Background" Value="Transparent"/>                    
        </Style>
    </UserControl.Resources>
    
    <StackPanel Name="MainStackPanel">
        <Grid x:Name="CondensedPanel" Visibility="Collapsed">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.02*"/>
                <ColumnDefinition Width="30"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Label Grid.Column="1" x:Name="txtCondensed" Content="שם: "></Label>
            <Label Grid.Column="2" x:Name="lblCondensed" Content="{Binding ld_name}"></Label>
            ....

Thank You,
Enjoy! 

WPF - Find Parent Control in VisualTree - Generics Methods

If you need to find parent control, but you would like to use generic method for find one, you can use
method I wrote:


public UIElement GetParent<TSource>(UIElement element, UIElement stopOn)
{
   while (element != null && !(element is TSource) && (element != stopOn))
   {
      element = VisualTreeHelper.GetParent(element) as UIElement;               
   }
   if (element == stopOn)
      return null;
   else
      return element;
}
and you can implement it like this:
UIElement expander = GetParent<Expander>(element, parent);
if ( expander != null)
     return;
P.S.
Its very helpful if you are using routed events of WPF (instance:PreviewMouseLeftButtonDown)
and you want to stop bubble events on one of control on the way.

יום חמישי, 7 באפריל 2011

WPF Data Binding Converter


Following Post explains how to create Converter for WPF data binding.
For example we need to bind Lable control to his Background propertie:


 <Label.Background>
                    <Binding Path="BranchColor">...

but in Data Source we are getting string instead of Color: Red, Blue, Green and so...

We need to create converter that will possible to convert string "colors" to System.Windows.Model class.

We need to perform following steps:



1. Write Converter class with converts and Converts back methods:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Globalization;
using System.Windows.Media;
using System.Drawing;

namespace GarageManager.Converters
{  
    [ValueConversion(typeof(decimal), typeof(string))]
    public class BrushesConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return null;
            BrushConverter convertor = new BrushConverter();
            return convertor.ConvertFromString(value.ToString());
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return null;
            BrushConverter convertor = new BrushConverter();
            return convertor.ConvertToString(value);
        }
    }
}

2. Register it on our XML file where we writing data binding:

xmlns:local="clr-namespace:GarageManager.Converters"

3. and perform data biding with converter:

 <Label x:Name="lblBranchColor"  Grid.Column="0" Grid.RowSpan="3" Width="5">
                <Label.Background>
                    <Binding Path="BranchColor">
                        <Binding.Converter>
                            <local:BrushesConverter></local:BrushesConverter>
                        </Binding.Converter>
                    </Binding>
                </Label.Background>
            </Label>

Hope it's HELPS,
Thanks,
Alex.

יום ראשון, 3 באפריל 2011

Add Double Click Event on TreeNode in Style


Followin code adding MouseDoubleClick Event to TreeView control in Style tag of XAML.
I think it' clear enough without explanations: 

 <TreeView Grid.Row="1"    
  x:Name="MainTreeView"
  Background="Transparent"
  HorizontalAlignment="Stretch"
  ItemsSource="{Binding List}"
  VerticalAlignment="Stretch" 
  ItemTemplate="{StaticResource ClassificationTemplate}" 
                 <TreeView.ItemContainerStyle>
                    <Style TargetType="{x:Type TreeViewItem}">
                        <EventSetter Event="MouseDoubleClick" Handler="OnTreeNodeDoubleClick"/>
                    </Style>
                 </TreeView.ItemContainerStyle>
 </TreeView>


Code Behind:

private void OnTreeNodeDoubleClick(object sender, MouseButtonEventArgs mouseEvtArgs)
{
   .....add your code here                    
}

Find String in WPF TreeView control


How to find string in TreeView control?
The biggest thing about WPF is data binding and so in WPF TreeView very important to what source you binded your TreeView.
For example my source will 3 hierarchical classes A, B and C:

public class A
{
   public string Filed {get; set;}
   List<B> bList = new List<B>();
}

public class B
{
   public string Filed {get; set;}
   List<C> bList = new List<C>();
}

public class C
{
   public string Filed {get; set;}
}


public void Main()
{
   A a = new A();
   B b = new B();
B bb = new B();
C c = new C();
C cc = new C();
C ccc = new C();
a.bList.Add(b);
a.bList.Add(bb);
b.cList.Add(c);
b.cList.Add(cc);
b.cList.Add(ccc);
}


And in XAML we created HierarchicalDataView with relevant DataBinding and got TreeView:

<HierarchicalDataTemplate x:Key="elementTemplate">   
 <StackPanel Orientation="Horizontal">
  <TextBlock Text="{Binding cList}"/>
    <TextBlock Text="{Binding NormaTimeCount, StringFormat= - כמות: {0}}"/>
 </StackPanel>
 </HierarchicalDataTemplate>
 <HierarchicalDataTemplate x:Key="chapterTemplate" 
   ItemsSource="{Binding Path=bList}"                   
   ItemTemplate="{StaticResource elementTemplate}">
   <Grid>
    <Grid.RowDefinitions>
    <RowDefinition></RowDefinition>
    <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
   <Grid.ColumnDefinitions>
    <ColumnDefinition></ColumnDefinition>
    <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock Text="{Binding ld_name}" Grid.Column="0" Grid.Row="0" />
   </Grid>
 </HierarchicalDataTemplate>
 <HierarchicalDataTemplate x:Key="ClassificationTemplate"                            ItemsSource="{Binding Path=Chapters.List}"                   
   ItemTemplate="{StaticResource chapterTemplate}">
   <Grid>
    <Grid.RowDefinitions>
    <RowDefinition></RowDefinition>
    <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
    <ColumnDefinition></ColumnDefinition>
    <ColumnDefinition></ColumnDefinition>
    <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock Text="{Binding ld_name}" Grid.Column="0" Grid.Row="0" />
  </Grid>
  </HierarchicalDataTemplate>

C# code:

private void btnFind_Click(object sender, RoutedEventArgs e)
{
   Find(_MainTreeView, textToFindt);
}

private void Find(TreeView mainTreeView, string findToText)
{
   foreach (object item in mainTreeView.Items)
   {
     TreeViewItem treeItem = mainTreeView.ItemContainerGenerator.ContainerFromItem(item) 
                                                                          as TreeViewItem;
                if (treeItem != null)
                    FindAll(treeItem, findText);
                if (item != null)
                {
                    dynamic obje = treeItem.Header;
                    if (isContains(obje.ld_name, findText))
                    {
                        treeItem.Focus();
                        treeItem.IsExpanded = true;
                        treeItem.Background = Brushes.Red;
                    }
                }
            }
        }
 
void FindAll(ItemsControl items, string textToFind)
        {
            foreach (object obj in items.Items)
            {
                ItemsControl childControl = items.ItemContainerGenerator.ContainerFromItem(obj) as ItemsControl;
                if (childControl != null)
                {
                    FindAll(childControl, findText); // Recursion
                }
                TreeViewItem item = childControl as TreeViewItem;
                if (item != null)
                {
                     //only if you dont know type of your Tree (in our case it's A, B or C and you need to use if or switch                        - case statement)
                    dynamic obje = item.Header;                     if (isContains(obje.ld_name, findText))                     {                         item.Focus();                         item.IsExpanded = true; // if you need to expand and show it                         item.Background = Brushes.Red;                     }                 }             }         }