Thomas Lebrun

All you need about WPF, Silverlight & LINQ !

March 2009 - Posts

[WPF] How to bind a control to a property defined in the Settings ?

Settings are a very powerful feature of .NET applications that allows developers to store some values in the settings of the application:

If you want to know how to bind a control to a property defined in the settings, it’s pretty simple. First, you need to add a custom XML namespace that will design the namespace where the settings are defined:

xmlns:properties="clr-namespace:TestSettings.Properties"

Then, in your XAML file, access the property using the following syntax:

x:Static properties:Settings.Default

So here is the final result code:

<ListBox x:Name="lb"

         ItemsSource="{Binding Source={x:Static properties:Settings.Default}, Path=Names}" />

That’s all :)

 

Happy coding !

 

Bye.

Posted: Mar 26 2009, 09:23 AM by Thomas Lebrun | with 17 comment(s)
Filed under: ,
[WPF] How to develop and editable Textblock ?

Here is another request that a friend of mine asked me recently. To achieve this, I’ve just create a custom control that contains a TextBlock and a TextBox (which is hidden) controls.

When user double clic on the TextBlock, the Textbox appears.

So here is my proposition: in the file generic.xaml, put this:

 

<Style TargetType="{x:Type local:EditableTextBlock}">

    <Setter Property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="{x:Type local:EditableTextBlock}">

                <Grid x:Name="PART_GridContainer"

                      Background="{TemplateBinding Background}"

                      Width="{TemplateBinding Width}"

                      Height="{TemplateBinding Height}">

                    <TextBlock x:Name="PART_TbDisplayText"

                               Visibility="Visible"

                               Background="{Binding Mode=TwoWay, Path=TextBlockBackgroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"

                               Foreground="{Binding Mode=TwoWay, Path=TextBlockForegroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"

                               Text="{Binding Mode=TwoWay, Path=Text, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}" />

                    <TextBox x:Name="PART_TbEditText"

                             Visibility="Hidden"

                             Background="{Binding Mode=TwoWay, Path=TextBoxBackgroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"

                             Foreground="{Binding Mode=TwoWay, Path=TextBoxForegroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"

                             Text="{Binding Mode=TwoWay, Path=Text, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}" />

                </Grid>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>

 

Then, here is the content that should go in the behind file:

 

[TemplatePart(Type = typeof(Grid), Name = EditableTextBlock.GRID_NAME)]

[TemplatePart(Type = typeof(TextBlock), Name = EditableTextBlock.TEXTBLOCK_DISPLAYTEXT_NAME)]

[TemplatePart(Type = typeof(TextBox), Name = EditableTextBlock.TEXTBOX_EDITTEXT_NAME)]

public class EditableTextBlock : Control

{

    #region Constants

    private const string GRID_NAME = "PART_GridContainer";

    private const string TEXTBLOCK_DISPLAYTEXT_NAME = "PART_TbDisplayText";

    private const string TEXTBOX_EDITTEXT_NAME = "PART_TbEditText";

    #endregion

    #region Member Fields

    private Grid m_GridContainer;

    private TextBlock m_TextBlockDisplayText;

    private TextBox m_TextBoxEditText;

    #endregion

    #region Dependency Properties

    public string Text

    {

        get { return (string)GetValue(TextProperty); }

        set { SetValue(TextProperty, value); }

    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(EditableTextBlock), new UIPropertyMetadata(string.Empty));

    public Brush TextBlockForegroundColor

    {

        get { return (Brush)GetValue(TextBlockForegroundColorProperty); }

        set { SetValue(TextBlockForegroundColorProperty, value); }

    }

    public static readonly DependencyProperty TextBlockForegroundColorProperty = DependencyProperty.Register("TextBlockForegroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));

    public Brush TextBlockBackgroundColor

    {

        get { return (Brush)GetValue(TextBlockBackgroundColorProperty); }

        set { SetValue(TextBlockBackgroundColorProperty, value); }

    }

    public static readonly DependencyProperty TextBlockBackgroundColorProperty = DependencyProperty.Register("TextBlockBackgroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));

    public Brush TextBoxForegroundColor

    {

        get { return (Brush)GetValue(TextBoxForegroundColorProperty); }

        set { SetValue(TextBoxForegroundColorProperty, value); }

    }

    public static readonly DependencyProperty TextBoxForegroundColorProperty = DependencyProperty.Register("TextBoxForegroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));

    public Brush TextBoxBackgroundColor

    {

        get { return (Brush)GetValue(TextBoxBackgroundColorProperty); }

        set { SetValue(TextBoxBackgroundColorProperty, value); }

    }

    public static readonly DependencyProperty TextBoxBackgroundColorProperty = DependencyProperty.Register("TextBoxBackgroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));

    #endregion

    #region Constructor

    static EditableTextBlock()

    {

        DefaultStyleKeyProperty.OverrideMetadata(typeof(EditableTextBlock), new FrameworkPropertyMetadata(typeof(EditableTextBlock)));

    }

    #endregion

    #region Overrides Methods

    public override void OnApplyTemplate()

    {

        base.OnApplyTemplate();

        this.m_GridContainer = this.Template.FindName(GRID_NAME, this) as Grid;

        if(this.m_GridContainer != null)

        {

            this.m_TextBlockDisplayText = this.m_GridContainer.Children[0] as TextBlock;

            this.m_TextBoxEditText = this.m_GridContainer.Children[1] as TextBox;

            this.m_TextBoxEditText.LostFocus += this.OnTextBoxLostFocus;

        }

    }

    protected override void OnMouseDoubleClick(MouseButtonEventArgs e)

    {

        base.OnMouseDoubleClick(e);

        this.m_TextBlockDisplayText.Visibility = Visibility.Hidden;

        this.m_TextBoxEditText.Visibility = Visibility.Visible;

    }

    #endregion

    #region Event Handlers

    private void OnTextBoxLostFocus(object sender, RoutedEventArgs e)

    {

        this.m_TextBlockDisplayText.Visibility = Visibility.Visible;

        this.m_TextBoxEditText.Visibility = Visibility.Hidden;

    }

    #endregion

}

 

As you can see, it’s pretty simple but very useful :)

Happy coding !

Bye.

Posted: Mar 24 2009, 08:16 AM by Thomas Lebrun | with 19 comment(s)
Filed under: ,
[Blend] XAML & Code Intellisense in Expression Blend 3

Version 3 of Expression Blend, which is available since last week, comes with a lot of new features. In this features, we can find Intellisense in XAML files:

image 

So it’s just a real please for people who, like me, modify the XAML code: no need to open Visual Studio to have Intellisense !

But, we can also see another interesting point: the code editor (which was present in the very first Beta of Expression Blend and disappear then) now is again available, with Intellisense on C# or VB.NET files:

image

image

For sure, it’s not a good idea to develop an application using only Expression Blend (don’t fordet that you cannot have breakpoints…) but for doing some tests or prototypes, it’s really nice !

Happy (Silverlight & WPF) coding !

Bye.

[WPF] Another sample of WPF application using the pattern MVVM

To help new developers, here is a sample WPF application (that use the Northwind database) developed by using the pattern MVVM (Model View ViewModel).

The goal of this little application is just to give another example that will help to understand this new pattern that is really powerful !

image

I will try to make some blog posts about this pattern quickly. In the meantime, just enjoy this :)

The application can be downloaded here: http://morpheus.developpez.com/wpf/tools/DemoMVVM.zip

Bye.

Posted: Mar 17 2009, 10:29 AM by Thomas Lebrun | with 13 comment(s) |
Filed under: , ,
[WPF] How to assign a dynamic resource from code-behind ?

When working on WPF projects, it’s mandatory to assign resources to user interface controls. When you work in XAML, it’s pretty simple: you just need to use the MarkupExtension named StaticResource (or DynamicResource if the resource is going to be modified):

<Button Content="Find Position" Click="Button_Click" Background="{DynamicResource brush}" />

But, how to do the same using code-behind ? The key is to use the method SetResourceReference (http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.setresourcereference.aspx):

<Window.Resources>

    <SolidColorBrush x:Key="brush" Color="Red" />

</Window.Resources>

 

<Button x:Name="btn"Content="Find Position" Click="Button_Click" />

 

this.btn.SetResourceReference(BackgroundProperty, "brush");

As you can see, it’s really simple to use: you define the resource, you define the control and, in code behind, you call the method SetResourceReference and use the following parameters:

  • the DependencyProperty on which the resource will be applied
  • the name of the resource

 

Happy coding !

Posted: Mar 11 2009, 11:46 AM by Thomas Lebrun | with 5 comment(s)
Filed under: ,
[WPF] How to gray the icon of a MenuItem ?

Here is a question that a friend of mine asked me recently. Indeed, as a beginner with WPF, it thought that setting the property IsEnabled = false, on the MenuItem, will disable it. So, the following code:

 

<MenuItem Header="Edit">

    <MenuItem x:Name="miPaste"

              Header="Paste" IsEnabled="False" >

        <MenuItem.Icon>

            <Image Source="pack://application:,,,/Images/Paste.png"

/>

        </MenuItem.Icon>

    </MenuItem>

</MenuItem>

 

Does not deactivate the image, as you can see here:

 

To correct this, you have 2 choices:

  • Use a second gray image which will be specified as the source for the control if this one is deactivated
  • Use the class FormatConvertedBitmap to create a gray image

 

So I’ve created a little class, AutoGreyableImage, which allow you to have an image that will be turn in gray automatically when the control is desactivated.

Here is how you can use it:

<MenuItem Header="Edit">

    <MenuItem x:Name="miPaste"

              Header="Paste">

        <MenuItem.Icon>

            <local:AutoGreyableImage Source="pack://application:,,,/Images/Paste.png"

                                                   />

        </MenuItem.Icon>

    </MenuItem>

</MenuItem>

 

And here is the implementation:

/// <summary>

/// Class used to have an image that is able to be gray when the control is not enabled.

/// Author: Thomas LEBRUN (http://blogs.developpeur.org/tom)

/// </summary>

public class AutoGreyableImage : Image

{

    /// <summary>

    /// Initializes a new instance of the <see cref="AutoGreyableImage"/> class.

    /// </summary>

    static AutoGreyableImage()

    {

        // Override the metadata of the IsEnabled property.

        IsEnabledProperty.OverrideMetadata(typeof(AutoGreyableImage), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnAutoGreyScaleImageIsEnabledPropertyChanged)));

    }

    /// <summary>

    /// Called when [auto grey scale image is enabled property changed].

    /// </summary>

    /// <param name="source">The source.</param>

    /// <param name="args">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>

    private static void OnAutoGreyScaleImageIsEnabledPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)

    {

        var autoGreyScaleImg = source as AutoGreyableImage;

        var isEnable = Convert.ToBoolean(args.NewValue);

        if (autoGreyScaleImg != null)

        {

            if (!isEnable)

            {

                // Get the source bitmap

                var bitmapImage = new BitmapImage(new Uri(autoGreyScaleImg.Source.ToString()));

                // Convert it to Gray

                autoGreyScaleImg.Source = new FormatConvertedBitmap(bitmapImage, PixelFormats.Gray32Float, null, 0);

                // Create Opacity Mask for greyscale image as FormatConvertedBitmap does not keep transparency info

                autoGreyScaleImg.OpacityMask = new ImageBrush(bitmapImage);

            }

            else

            {

                // Set the Source property to the original value.

                autoGreyScaleImg.Source = ((FormatConvertedBitmap) autoGreyScaleImg.Source).Source;

                // Reset the Opcity Mask

                autoGreyScaleImg.OpacityMask = null;

            }

        }

    }

}

 

Here is the result:

You can download the sources (and the demo) here: http://morpheus.developpez.com/wpf/DisableMenuItemIcon.zip/wpf/DisableMenuItemIcon.zip

Happy coding !

 

Posted: Mar 03 2009, 09:40 AM by Thomas Lebrun | with 14 comment(s)
Filed under: ,
More Posts