tags:

views:

574

answers:

1

I have the following class:

public class Day
{
    public int Date { get; set; }
    public String DayName { get; set; }

    public Day()
    {

    }

    public Day(int date, string dayName)
    {
        Date = date;
        DayName = dayName;

        CommandManager.RegisterClassCommandBinding(typeof(Day), new CommandBinding(DayClick, new ExecutedRoutedEventHandler(OnExecutedDayClick), 
            new CanExecuteRoutedEventHandler(OnCanExecuteDayClick)));
    }

    public static readonly RoutedCommand DayClick = new RoutedCommand("DayClick", typeof(Day));

    private static void OnCanExecuteDayClick(object sender, CanExecuteRoutedEventArgs e)
    {
        ((Day)sender).OnCanExecuteDayClick(e);
    }

    private static void OnExecutedDayClick(object sender, ExecutedRoutedEventArgs e)
    {
        ((Day)sender).OnExecutedDayClick(e);
    }

    protected virtual void OnCanExecuteDayClick(CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
        e.Handled = false;
    }

    protected virtual void OnExecutedDayClick(ExecutedRoutedEventArgs e)
    {
        string content = String.Format("Day {0}, which is {1}, was clicked.", Date.ToString(), DayName);
        MessageBox.Show(content);
        e.Handled = true;
    }
}

I am using the following DataTemplate (that is in a ResourceDictionary) to render it:

<DataTemplate DataType="{x:Type local:Day}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Rectangle Grid.ColumnSpan="2" x:Name="rectHasEntry" Fill="WhiteSmoke"/>
        <TextBlock Grid.Column="0" x:Name="textBlockDayName" Text="{Binding DayName}" 
                               FontFamily="Junction" FontSize="11" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,2,0,0"/>
        <TextBlock Grid.Column="1" x:Name="textBlockDate" Text="{Binding Date}" 
                               FontFamily="Junction" FontSize="11" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,2,0,0"/>
        <Rectangle Grid.ColumnSpan="2" x:Name="rectMouseOver" Fill="#A2C0DA" Opacity="0"
                               Style="{StaticResource DayRectangleMouseOverStyle}">
        </Rectangle>
    </Grid>
</DataTemplate>

No problems so far, I can get it on screen.

What I want to be able to do is assign a Command, or use an event, so that when the user clicks on the Day it will notify the parent of the Day object that it has been clicked.

I've tried the following:

<Rectangle.CommandBindings>
    <CommandBinding Command="{x:Static local:Day.NextDay}"
                             Executed="{x:Static local:Day.OnExecutedDayClick}"
                             CanExecute="{x:Static local:Day.OnCanExecuteDayClick}"/>
</Rectangle.CommandBindings>

to try and bind the commands that are in the Day class but it didn't work. I got an error stating:

'ResourceDictionary' root element requires a x:Class attribute to support event handlers in the XAML file. Either remove the event handler for the Executed event, or add a x:Class attribute to the root element.

Which I think means that there is no code-behind file for a ResourceDictionary, or something to that effect.

In any event, I'm not sure if I should be using Commands here, or somehow tying events to the Rectangle in question, or if this is even possible. I've seen various places where it sure looks like it's possible, I'm just unable to translate what I'm seeing into something that actually works, hence this post.

Thanks in advance.

A: 

You cann't declare CommandBinding here, in this case you can assign the command here in DataTemplate and declare CommandBinding in your main Window or Page.

Edit:

In this way you can use Commands with your custom control. Create a custom control and Declare Commands and Command Bindings also inside the control itself as in this Sample.

MyCustomControl.cs

    static MyCustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
        InitializeCommands();
    }

    private static RoutedCommand _myCommand;

    public static RoutedCommand MyCommand
    {
        get
        {
            return _myCommand;
        }
    }

    private static void InitializeCommands()
    {
        _myCommand = new RoutedCommand("MyCommand", typeof(MyCustomControl));
        CommandManager.RegisterClassCommandBinding(typeof(MyCustomControl),
                                new CommandBinding(_myCommand , OnMyCommandExecute));
    }

    private static void OnMyCommandExecute(object sender, ExecutedRoutedEventArgs e)
    {
        MyCustomControl control = sender as MyCustomControl;
        if (control != null)
        {
            //logic for this command
        }
    }

and in your generic.xaml write this style and assign commands like this:

generic.xaml

<Style TargetType="{x:Type local:MyCustomControl}">
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyCustomControl}">
                <Grid>
                    <RepeatButton Command="{x:Static local:MyCustomControl.MyCommand}"  >Click</RepeatButton>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
viky
If I wanted to make this a control that lived in a CustomControls assembly so that it could be re-used in other apps, where would I declare the commandbindings then? Because the click code would always be the same and I would want it handled by the control and not by the mainwindow or page of the application that was using it.
Scott
I have updated my answer!!
viky
That's what I was looking for, thank you very much.
Scott