#826 – Lower-Level Elements Can Have Different Cursor

Cursor set on a top-level FrameworkElement will also be used on all elements within the parent element’s logical tree.  All lower-level elements will show the same cursor when the user hovers over the element.

You can, however, set a Cursor on a top-level element and then set a different value for Cursor on the lower-level element.  The top-level Cursor will be used for all descendants of the top-level element except for the one that explicitly sets a different cursor.

    <StackPanel Cursor="Hand">
        <Label Content="Ad eundum quo nemo ante iit"
               Margin="5"
               Background="LightCoral"/>
        <Label Content="Noli habere bovis, vir"
               Margin="5"
               Background="DarkSeaGreen"/>
        <StackPanel Orientation="Horizontal"
                    HorizontalAlignment="Center">
            <Button Content="Veni, Vidi"
                    Padding="10,5" Margin="10"/>
            <Button Content="Dormivi"
                    Cursor="Wait"
                    Padding="10,5" Margin="10"/>
        </StackPanel>
    </StackPanel>

826-001
826-002

#825 – Two Way Binding for a CheckBox

You can bind the IsChecked property of a CheckBox to a boolean variable, so that the variable will always reflect the current value of the CheckBox in the user interface.

You can also do two-way binding, where the boolean variable changes when the user toggles the CheckBox, but the CheckBox also toggles when the value of the variable changes.

        <Label Content="Things my dog can do:"/>
        <CheckBox Content="Sit" IsChecked="{Binding CanSit, Mode=TwoWay}"/>
        <CheckBox Content="Stay" IsChecked="{Binding CanStay, Mode=TwoWay}"/>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="Report State" Click="btnReportState_Click"
                    Margin="5"/>
            <Button Content="Change State" Click="btnChangeState_Click"
                    Margin="5"/>
        </StackPanel>

Code-behind:

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private bool canSit;
        public bool CanSit
        {
            get { return canSit; }
            set
            {
                canSit = value;
                RaisePropertyChanged("CanSit");
            }
        }

        private bool canStay;
        public bool CanStay
        {
            get { return canStay; }
            set
            {
                canStay = value;
                RaisePropertyChanged("CanStay");
            }
        }

        public MainWindow()
        {
            this.InitializeComponent();
            this.DataContext = this;
        }

        private void btnReportState_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(string.Format("Sit: {0}, Stay: {1}", CanSit, CanStay));
        }

        private void btnChangeState_Click(object sender, RoutedEventArgs e)
        {
            CanSit = CanSit ? false : true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }

#824 – Setting a Cursor on a Top Level Element

When you set the Cursor property on a FrameworkElement, the cursor is displayed whenever you move the mouse pointer over that element.  This Cursor value will also apply to all descendants of the element.

In the example below, when we set the Cursor in the top-level Window, that cursor is used for all elements contained in the window.

Layout, within the Window:

    <StackPanel>
        <Label Content="Ad eundum quo nemo ante iit"
               Margin="5"
               Background="LightCoral"/>
        <Label Content="Noli habere bovis, vir"
               Margin="5"
               Background="DarkSeaGreen"/>
        <StackPanel Orientation="Horizontal"
                    HorizontalAlignment="Center">
            <Button Content="Veni, Vidi"
                    Padding="10,5" Margin="10"
                    Click="btnClick_Wait"/>
            <Button Content="Dormivi"
                    Padding="10,5" Margin="10"
                    Click="btnClick_StopWaiting"/>
        </StackPanel>
    </StackPanel>

Code-behind:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnClick_Wait(object sender, RoutedEventArgs e)
        {
            this.Cursor = Cursors.AppStarting;
        }

        private void btnClick_StopWaiting(object sender, RoutedEventArgs e)
        {
            this.Cursor = Cursors.Arrow;
        }
    }

824-001
824-002
824-003
824-004
824-005

#823 – Setting a Cursor from XAML

Every FrameworkElement has a Cursor property that you can set to an instance of a System.Windows.Input.Cursor object.  Typically, you’ll just set the property to one of the predefined cursors in the System.Windows.Input.Cursors class.

When you set the Cursor property on an element, you’re indicating which cursor should appear when a user moves the mouse over that element.

You can set the Cursor property in XAML or in code.  In either case, you can pick from one of the predefined cursors in System.Windows.Input.Cursors.  In the image below, Intellisense in Visual Studio shows a list of the available cursors when setting the Cursor property from XAML.

823-001

In the example below, we indicate that we want the Wait cursor displayed whenever we hover over the second label.

    <StackPanel>
        <Label Content="I'm just a label, you know?"
               Margin="5"
               Background="LightCoral"/>
        <Label Content="I'm waiting and waiting"
               Margin="5"
               Background="DarkSeaGreen"
               Cursor="Wait"/>
    </StackPanel>

823-002
823-003

#822 – Deciding which TextFormattingMode to Use

The TextOptions.TextFormattingMode property indicates whether fonts should be formatted using the standard WPF algorithm or the legacy GDI method for positioning the individual glyphs in the font.  The property can have one of the following values:

  • Ideal – Default value, formats text using the standard WPF method.  Glyph shapes are preserved, independent of their final position on the display
  • Display – Positions edges of glyphs on pixel boundaries.  Can result in clearer edges of text.

You should use the value of Ideal, except for the situations listed below.

Set TextFormattingMode to Display when all of the following is true:

  • The FontSize of the text is 14 or less  (small text)
  • Text is not being transformed (scaled, rotated, translated)
  • The exact shape of the glyphs is not critical (e.g. for some graphic design scenario)

#821 – Use TextFormattingMode to Make Text Look More Clear

WPF tries to retain the exact shape and style of each glyph in a font, no matter what size the font is being rendered at.  This means that as the text gets smaller, relative to the pixel density of the display, the edges of the glyphs may no longer occur at pixel boundaries.  When this happens, WPF will use anti-aliasing to render the edges of the glyphs in a different color.  This can lead to small text looking fuzzy, or having some odd color fragments along the edges of the letters.

To avoid fuzzy text at small sizes, you can set the TextOptions.TextFormattingMode property to Display (as opposed to the default value of Ideal).  This tells WPF to align the glyphs at pixel boundaries, which can lead to crisper/cleaner text.

        <TextBlock Text="WiWi WIWI HaHaHa (Ideal = Default)"
                   Margin="5"/>
        <TextBlock Text="WiWi WIWI HaHaHa (Display)"
                   TextOptions.TextFormattingMode="Display"
                   Margin="5"/>

821-001

#820 – Viewing Additional Font Properties in Windows Explorer

You can preview TrueType fonts in Windows Explorer and also get some basic properties about each font.  If you right-click on a font file, select Properties and then select the Details tab, you’ll see some basic information:

820-001

You can also download a Microsoft-provided tool, the OpenType Font File Properties Extension, to get even more information about each font.  You can download the tool from here.  (This tool will only work on 32-bit operating systems).

After installing the extension tool, the properties dialog for a font file will contain a number of additional tabs.

  • Embedding – Are you allowed to embed the font in your application?
  • CharSet/Unicode – What encoding method is used (e.g. Unicode)
  • Links – (optional) URL to font vendor
  • Description – General info on the font
  • License – license information
  • Version – font version
  • Hinting/Font Smoothing – point sizes for hinting/smoothing
  • Names – Font name, font family name, vendor, etc.
  • Features – Description from vendor

820-002

820-003

 

 

Follow

Get every new post delivered to your Inbox.

Join 233 other followers