Contents tagged with WPF

  • The CLR, Dependency Properties, Routed Events and Cider

    Dependency Properties and Routed Events are special WPF mechanisms that can be used in place of the CLR's normal Properties and Events, since they are more powerful, although less typed. You can even define a dependency property or routed event without a matching property or event and one can access the property's value or attach to the event using simple code.

    Read more...

  • Two Birds with One Stone: Introducing The MultiBindingFoldingConverter

    After realizing the project I'm working on is in need of two features that do not exist in WPF - one being a missing feature, the other being a bug - I decided to take action and write something that would allow one to write code that is currently an unsupported scenario.

    First, let's take a look at what we want accomplish. We have the following Window, that shows the speed we're walking at. It has three combo boxes, signifying (from left to right) the language of the form (English or Dutch), the distance measurement units (Meters or Kilometres) and the time measurement units (Seconds or Hours), along with a text box that indicates the speed we're walking (as measured in KM/H). What we would like to do is to translate this information to a single string. This is how we would have done this, if the above mentioned features were not missing:

    The above illustration shows a single converter (a call to string.Format) which would receive 5 values - the format (language specific, so it has to be converted using a converter), the text for "Speed" (same as the format - must be converted to the wanted language), the speed itself (after being converted from its original value to the requested distance and time unit types) and the distance and time unit types' names (converted to the language of our choice).

    However, this scenario is impossible in today's WPF, so in its stead, I have created the MultiBindingFoldingConverter, which allows you to create the above tree with the following XAML:

    <MultiBinding Mode="OneWay">
        <MultiBinding.Converter>
            <f:MultiBindingFoldingConverter>
                <f:Fold Converter="{StaticResource stringFormatConverter}">
                    <!-- Format -->
                    <f:BindingReference Index="0"
                        Converter="{StaticResource translationConverter}"
                        ConverterParameter="Format" />
                    <!-- "Speed" -->
                    <f:BindingReference Index="0"
                        Converter="{StaticResource translationConverter}"
                        ConverterParameter="Speed" />
                    <!-- Speed value -->
                    <f:Fold
                        Converter="{StaticResource speedConverter}">
                        <!-- Speed -->
                        <f:BindingReference Index="1" />
                        <!-- Distance -->
                        <f:BindingReference Index="2" />
                        <!-- Time -->
                        <f:BindingReference Index="3" />
                    </f:Fold>
                    <!-- Distance -->
                    <f:Fold
                        Converter="{StaticResource translationConverter}">
                        <f:BindingReference Index="0" />
                        <f:BindingReference Index="2" />
                    </f:Fold>
                    <!-- Time -->
                    <f:Fold
                        Converter="{StaticResource translationConverter}">
                        <f:BindingReference Index="0" />
                        <f:BindingReference Index="3" />
                    </f:Fold>
                </f:Fold>
            </f:MultiBindingFoldingConverter>
        </MultiBinding.Converter>
        <!-- Language -->
        <Binding ElementName="language" Path="SelectedItem" />
        <!-- Speed -->
        <Binding ElementName="speed" Path="Text" />
        <!-- Distance -->
        <Binding ElementName="distance" Path="SelectedItem" />
        <!-- Time -->
        <Binding ElementName="time" Path="SelectedItem" />
    </MultiBinding>
    

    Instead of writing the Binding elements hierarchically, you simply write the logic of the conversion hierarchy using Fold (instead of MultiBinding) and BindingReference (instead of Binding) elements.

    BindingReference elements are exactly what you'd guess they were - references to individual binding tags inside the original MultiBinding, using their zero-based index. For instance, the first BindingReference receives its value from the zeroth Binding element, i.e. the language binding.
    Fold elements take their child BindingReference and Fold elements and fold them into a single value, much like a MultiBinding element folds many Binding elements.
    Both BindingReference and Fold elements are Evaluators, which means that they can use a value converter (IValueConverter and IMultiValueConverter respectively), along with its parameter and a culture. A Mode attribute can also be placed on them, much like one would be placed on a Binding (updating the source is not fully supported and tested, simply because I have yet to find a case in which I would need it).

    An additional upside to this solution is the fact that each Binding happens only once per calculation, so in our example, rather than have 9 Binding elements along with 4 more MultiBinding elements, we only have 4 Binding elements and one MultiBinding.

    The code and sample are both available on a new project I opened on CodePlex, under the DotNetZen.Presentation.Converters and Converters projects respectively. I intend to keep adding new ideas and code to that repository as I go along. There's no release, but you can browse the source code itself and download a zip file of the entire code base.

    Read more...

  • Three Ways To Create Dynamic Menus

    There are quite a few sources about how to create dynamic menus (menus that are not embedded in XAML or code, but rather loaded from an external file):

    Read more...