Tag Archives: Binding

BindableApplicationBar RC1 + Windows Phone Prism Application Template

Today marks the RC1 release of the BindableApplicationBar. I have spent some time today to do some StyleCop and documentation cleanup and it seems ready. You can grab a zip file with the binary directly from here.

Another part of what I have been working on today is a Windows Phone application template. I have spent too many times working on boilerplate code and cleaning up the default Windows Phone Application template and decided to create something that will get me up to speed faster every time I want to create a phone app. It is called Windows Phone Prism Application and is available as a Visual Studio project template here.

Continue reading

Tagged , , , , , , , , , , , ,

The quest for a Bindable ApplicationBar – Part 3

This is it – for now at least. The BindableApplicationBar meets all the original requirements and while I found some new ones that might be achievable – it might already be in many ways the richest solution to the problem.

DataContext Changes

Continue reading

Tagged , , , , , , , , ,

The quest for a Bindable ApplicationBar – Part 2

Seems like the application bar finally works for predefined buttons. Next step – binding to ItemsSource-like view model collections for buttons and menu items and getting “ElementName bindings” to work…

For now – this will have to be it. I am sharing my library and test projects here.

Continue reading

Tagged , , , , , , , , ,

Workaround for binding not supported on Style/Setter/Value in Silverlight

This morning I was trying to bind the Orientation property of a PanoramaItem to a panorama item view model bound to the Panorama through its ItemsSource property and kept getting this weird exception when Silverlight was parsing the xaml stating that it “Cannot set read-only property”. I tried working around that and have some sort of attached property that would be bound to Orientation property of the view model and update the PanoramaItem’s Orientation property, but that produced the same result…

Well, it just so turns out – it is one of those things that are supported in WPF, but not in Silverlight

As a workaround – I created some attached dependency properties that are not bound to the view model themselves, but specify just the binding path and when set – create a binding to the PanoramaItem properties – as below…

public static class BindingBuilder
{
    #region PanoramaItemOrientation
    /// <summary>
    /// PanoramaItemOrientation Attached Dependency Property
    /// </summary>
    public static readonly DependencyProperty PanoramaItemOrientationProperty =
        DependencyProperty.RegisterAttached(
            "PanoramaItemOrientation",
            typeof(string),
            typeof(BindingBuilder),
            new PropertyMetadata(null, OnPanoramaItemOrientationChanged));

    /// <summary>
    /// Gets the PanoramaItemOrientation property. This dependency property
    /// indicates the binding path for the PanoramaItem.Orientation binding.
    /// </summary>
    public static string GetPanoramaItemOrientation(DependencyObject d)
    {
        return (string)d.GetValue(PanoramaItemOrientationProperty);
    }

    /// <summary>
    /// Sets the PanoramaItemOrientation property. This dependency property
    /// indicates the binding path for the PanoramaItem.Orientation binding.
    /// </summary>
    public static void SetPanoramaItemOrientation(DependencyObject d, string value)
    {
        d.SetValue(PanoramaItemOrientationProperty, value);
    }

    /// <summary>
    /// Handles changes to the PanoramaItemOrientation property.
    /// </summary>
    private static void OnPanoramaItemOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        string oldPanoramaItemOrientation = (string)e.OldValue;
        string newPanoramaItemOrientation = (string)d.GetValue(PanoramaItemOrientationProperty);
        var panoramaItem = (PanoramaItem)d;

        panoramaItem.SetBinding(PanoramaItem.OrientationProperty, new Binding(newPanoramaItemOrientation));
    }
    #endregion

    #region PanoramaItemHeader
    /// <summary>
    /// PanoramaItemHeader Attached Dependency Property
    /// </summary>
    public static readonly DependencyProperty PanoramaItemHeaderProperty =
        DependencyProperty.RegisterAttached(
            "PanoramaItemHeader",
            typeof(string),
            typeof(BindingBuilder),
            new PropertyMetadata(null, OnPanoramaItemHeaderChanged));

    /// <summary>
    /// Gets the PanoramaItemHeader property. This dependency property
    /// indicates the binding path for the PanoramaItem.Header binding.
    /// </summary>
    public static string GetPanoramaItemHeader(DependencyObject d)
    {
        return (string)d.GetValue(PanoramaItemHeaderProperty);
    }

    /// <summary>
    /// Sets the PanoramaItemHeader property. This dependency property
    /// indicates the binding path for the PanoramaItem.Header binding.
    /// </summary>
    public static void SetPanoramaItemHeader(DependencyObject d, string value)
    {
        d.SetValue(PanoramaItemHeaderProperty, value);
    }

    /// <summary>
    /// Handles changes to the PanoramaItemHeader property.
    /// </summary>
    private static void OnPanoramaItemHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        string oldPanoramaItemHeader = (string)e.OldValue;
        string newPanoramaItemHeader = (string)d.GetValue(PanoramaItemHeaderProperty);
        var panoramaItem = (PanoramaItem)d;

        panoramaItem.SetBinding(PanoramaItem.HeaderProperty, new Binding(newPanoramaItemHeader));
    }
    #endregion
}

Now I can have my Panorama built dynamically from its ItemsSource binding while still supporting setting of the PanoramaItems’ orientation and header through binding:

<Controls:Panorama
    DataContext="{Binding Panorama}"
    ItemsSource="{Binding Items}"
    Title="{Binding Title}"
    Background="{Binding Background}">
    <Controls:Panorama.ItemContainerStyle>
        <Style
            TargetType="Controls:PanoramaItem">
            <Setter
                Property="CacheMode"
                Value="BitmapCache" />
            <Setter
                Property="HorizontalContentAlignment"
                Value="Stretch" />
            <Setter
                Property="VerticalContentAlignment"
                Value="Stretch" />
            <Setter
                Property="local:BindingBuilder.PanoramaItemOrientation"
                Value="Orientation" />
            <Setter
                Property="local:BindingBuilder.PanoramaItemHeader"
                Value="HeaderText" />
            <Setter
                Property="Template">
                <Setter.Value>
                    <ControlTemplate
                        TargetType="Controls:PanoramaItem">
                        <Grid
                            Background="{TemplateBinding Background}"
                            Margin="12,0,0,0″>
                            <Grid.RowDefinitions>
                                <RowDefinition
                                    Height="auto" />
                                <RowDefinition
                                    Height="*" />
                            </Grid.RowDefinitions>
                            <ContentControl
                                x:Name="header"
                                ContentTemplate="{TemplateBinding HeaderTemplate}"
                                Content="{TemplateBinding Header}"
                                FontSize="{StaticResource PhoneFontSizeExtraExtraLarge}"
                                FontFamily="{StaticResource PhoneFontFamilySemiLight}"
                                HorizontalAlignment="Left"
                                Margin="10,-2,0,26″>
                                <ContentControl.RenderTransform>
                                    <TranslateTransform
                                        x:Name="headerTransform" />
                                </ContentControl.RenderTransform>
                            </ContentControl>
                            <ContentPresenter
                                Content="{TemplateBinding Content}"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                Margin="{TemplateBinding Padding}"
                                Grid.Row="1″
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Controls:Panorama.ItemContainerStyle>
</Controls:Panorama>

Then again – you could use the generic solution…

Tagged , , , , , , , ,

The quest for a Bindable ApplicationBar – Part 1

The funny thing about MVVM is that you might get so hooked on it that when you find something that just does not work with MVVM – you start trying to figure out how to bend it to the right path. One of such things is the ApplicationBar on Windows Phone.

Continue reading

Tagged , , , , , , , , ,

Using attached properties to style RowDefinitions of a Grid in WPF

The below sample shows how you can use attached dependency properties to style a Grid’s RowDefinitions. This specific case shows how a single property can be set to specify the number of rows in a Grid.

<Window
    x:Class="GridExtensions.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:GridExtensions="clr-namespace:GridExtensions"
    Title="MainWindow"
    Height="350"
    Width="525">
    <Grid>
        <Grid.Style>
            <Style>
                <Setter Property="GridExtensions:Griddier.RowsCount" Value="4"/>
            </Style>
        </Grid.Style>
        <TextBlock Grid.Row="0" Text="0"/>
        <TextBlock Grid.Row="1" Text="1"/>
        <TextBlock Grid.Row="2" Text="2"/>
        <TextBlock Grid.Row="3" Text="3"/>
    </Grid>
</Window>
namespace GridExtensions
{
    using System;
    using System.Windows;
    using System.Windows.Controls;

    public static class Griddier
    {
        #region RowsCount

        /// <summary>
        /// RowsCount Attached Dependency Property
        /// </summary>
        public static readonly DependencyProperty RowsCountProperty =
            DependencyProperty.RegisterAttached("RowsCount", typeof(int), typeof(Griddier),
                new FrameworkPropertyMetadata((int)0,
                    new PropertyChangedCallback(OnRowsCountChanged)));

        /// <summary>
        /// Gets the RowsCount property. This dependency property 
        /// indicates the number of star-heighted row definitions to include with the grid.
        /// </summary>
        public static int GetRowsCount(DependencyObject d)
        {
            return (int)d.GetValue(RowsCountProperty);
        }

        /// <summary>
        /// Sets the RowsCount property. This dependency property 
        /// indicates the number of star-heighted row definitions to include with the grid.
        /// </summary>
        public static void SetRowsCount(DependencyObject d, int value)
        {
            d.SetValue(RowsCountProperty, value);
        }

        /// <summary>
        /// Handles changes to the RowsCount property.
        /// </summary>
        private static void OnRowsCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d == null)
                throw new ArgumentNullException("d");
            var grid = d as Grid;
            if (grid == null)
                throw new ArgumentException("d should be of type Grid.", "d");
            int newRowsCount = (int)d.GetValue(RowsCountProperty);

            if (grid.RowDefinitions.Count > newRowsCount)
                while (grid.RowDefinitions.Count > newRowsCount)
                    grid.RowDefinitions.RemoveAt(newRowsCount);

            var gl = (GridLength)(new GridLengthConverter().ConvertFromString("*"));

            for (int i = 0; i < newRowsCount; i++)
            {
                if (grid.RowDefinitions.Count > i)
                    grid.RowDefinitions[i].Height = gl;
                else
                    grid.RowDefinitions.Add(new RowDefinition {Height = gl});
            }
        }

        #endregion
    }
}
Tagged , , , , , ,