lundi 29 juin 2015

Wpf Caliburn Micro: binding click event of faked captioned Rectangle

I use VS2013, Wpf 4.5 and Caliburn Micro. I want to use a Rectangle and to put TextBlock in it. I found a solution here in StackOverflow: put the rectangle and the textblock in a grid. It works.

Then I want to catch click event if user click on the rectangle. So I add x:Name="ClickMe" attribute in tag to bind click event to view model. It works, but only if the mouse points on non-text area of rectangle. As soon as the mouse pointer is on TextBlock area, the click event is ignored!

My first try: bind the TextBlock using x:Name="ClickText1" to event handler ClickText1(). It doesn't work. It seems TextBlock has no Click event.

My second try: I tried to put the TextBlock in a StackPanel, bind the StackPanel using x:Name="ClickStack" and the event handler ClickStack() will calls the ClickMe(). It doesn't work since the ClickStack() is called as soon as the application is started and before he view is shown. So my try is failed!

What I want: the whole rectangle area should be clicable (and raise click event) regardless text-area or non-text-area and the click event can be bound to ONE event handler in view model. All should work in caliburn micro pattern and no code-behind.

I attach my sample code below. Please feel free to modify it and show me how to solve it. You may also suggest me other simple way to put text on rectangle without using grid. But please don't suggest me to use Button control due to requirement of my project. Thank you in advance.

The View:

<UserControl x:Class="CMWpfShapeWithCaption.Views.ShellView"
         xmlns="http://ift.tt/o66D3f"
         xmlns:x="http://ift.tt/mPTqtT"
         xmlns:d="http://ift.tt/pHvyf2"
         xmlns:mc="http://ift.tt/pzd6Lm"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">
    <Grid Width="300"
          Height="300"
          ShowGridLines="False">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20*" />
            <ColumnDefinition Width="20*" />
            <ColumnDefinition Width="20*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20*" />
            <RowDefinition Height="20*" />
            <RowDefinition Height="20*" />
        </Grid.RowDefinitions>
        <Rectangle x:Name="ClickMe"
                   Grid.Row="1"
                   Grid.Column="1"
                   Fill="Aqua" />
        <StackPanel Grid.Row="1"
                    Grid.Column="1"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center">
             <TextBlock x:Name="ClickText1"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Text="{Binding Path=Text1}"
                        TextWrapping="Wrap" />
             <TextBlock HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Text="{Binding Path=Text2}"
                        TextWrapping="Wrap" />
         </StackPanel>
     </Grid>
</UserControl>

The view model:

using System;
using System.Windows;
using Caliburn.Micro;

namespace CMWpfShapeWithCaption.ViewModels
{
    public class ShellViewModel : PropertyChangedBase
    {
        public ShellViewModel()
        {
            Text1 = "Text1";
            Text2 = "Text2";
        }
        public String Text1 { get; set; }
        public String Text2 { get; set; }

        // Problem: this will be called only if Mouse points non-text area of grid
        // Target: This should be called regardless non-text or text-area,
        // as long as the mouse is clicked within rectangle area.
        public void ClickMe()
        {
            MessageBox.Show("Panel is clicked");
        }

        // This trick doesn't work at all.
        // It seems TextBlock has no click event?
        public void ClickText1()
        {
            ClickMe();
        }
    }
}

Aucun commentaire:

Enregistrer un commentaire