WPF Lookless Control Events

Posted by Scott on Stack Overflow See other posts from Stack Overflow or by Scott
Published on 2010-03-30T19:38:35Z Indexed on 2010/03/30 20:43 UTC
Read the original article Hit count: 450

Filed under:
|
|

I have the following class:

public class LooklessControl : Control
{
    public List<int> IntList { get; private set; }
    public int CurrentInt { get; private set; }

    private int _index = 0;

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

    public LooklessControl()
    {
        IntList = new List<int>();
        for (int i = 0; i < 10; i++)
        {
            IntList.Add(i);
        }
        CurrentInt = IntList[_index];
    }

    public static readonly RoutedCommand NextItemCommand =
        new RoutedCommand("NextItemCommand", typeof(LooklessControl));

    private void ExecutedNextItemCommand(object sender, ExecutedRoutedEventArgs e)
    {
        NextItemHandler();
    }

    private void CanExecuteNextItemCommand(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    public static readonly RoutedCommand PrevItemCommand =
        new RoutedCommand("PrevItemCommand", typeof(LooklessControl));

    private void ExecutedPrevItemCommand(ExecutedRoutedEventArgs e)
    {
        PrevItemHandler();
    }

    private void CanExecutePrevItemCommand(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }


    public static readonly RoutedEvent NextItemEvent =
        EventManager.RegisterRoutedEvent("NextItemEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(LooklessControl));

    public event RoutedEventHandler NextItem
    {
        add { AddHandler(NextItemEvent, value); }
        remove { RemoveHandler(NextItemEvent, value); }
    }

    private void RaiseNextItemEvent()
    {
        RoutedEventArgs args = new RoutedEventArgs(LooklessControl.NextItemEvent);
        RaiseEvent(args);
    }

    public static readonly RoutedEvent PrevItemEvent =
        EventManager.RegisterRoutedEvent("PrevItemEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(LooklessControl));

    public event RoutedEventHandler PrevItem
    {
        add { AddHandler(PrevItemEvent, value); }
        remove { RemoveHandler(PrevItemEvent, value); }
    }

    private void RaisePrevItemEvent()
    {
        RoutedEventArgs args = new RoutedEventArgs(LooklessControl.PrevItemEvent);
        RaiseEvent(args);
    }

    private void NextItemHandler()
    {
        _index++;
        if (_index == IntList.Count)
        {
            _index = 0;
        }

        CurrentInt = IntList[_index];
        RaiseNextItemEvent();
    }

    private void PrevItemHandler()
    {
        _index--;
        if (_index == 0)
        {
            _index = IntList.Count - 1;
        }

        CurrentInt = IntList[_index];
        RaisePrevItemEvent();
    }
}

The class has a default style, in Generic.xaml, that looks like this:

<Style x:Key="{x:Type local:LooklessControl}" TargetType="{x:Type local:LooklessControl}">
    <Setter Property="Height" Value="200"/>
    <Setter Property="Width" Value="90"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:LooklessControl}">
                <Border BorderBrush="Black" BorderThickness="1" Padding="2">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Rectangle Grid.Row="0" Fill="LightGray"/>
                        <Rectangle Grid.Row="1" Fill="Gainsboro"/>
                        <Grid Grid.Row="0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="10"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="10"/>
                            </Grid.ColumnDefinitions>
                            <Path Grid.Column="0" x:Name="pathLeftArrow" Data="M0,0.5 L1,1 1,0Z" Width="6" Height="14" Stretch="Fill"
                                  HorizontalAlignment="Center" Fill="SlateBlue"/>
                            <TextBlock Grid.Column="1" Name="textBlock" 
                                   Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CurrentInt}" 
                                   HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Junction" FontSize="13"/>
                            <Path Grid.Column="2" x:Name="pathRightArrow" Data="M0,0 L1,0.5 0,1Z" Width="6" Height="14" Stretch="Fill"
                                  HorizontalAlignment="Center" Fill="SlateBlue"/>
                        </Grid>
                        <ListBox Grid.Row="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" 
                             ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IntList}"/>
                    </Grid>
                </Border>                    
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

How do I make it so that when the user clicks on pathLeftArrow it fires LooklessControl.PrevItemCommand, or or they click on pathRightArrow and it fires LooklessControl.NextItemCommand, or they click on an item in the ListBox and LooklessControl is notified of the newly selected item?

In other words, without adding x:Class to the top of Generic.xaml and thus creating a code-behind file for it, which I assume you wouldn't want to do, how do you handle events for elements in your xaml that don't have a Command property (which is just about everything other than a Button)?

Should LooklessControl have it's own XAML file (much like what you get when you create a new UserControl) associated with it that Generic.xaml just pulls in as a MergedDictionar as its default template? Or is there some other acknowledged way to do what I'm trying to do?

© Stack Overflow or respective owner

Related posts about wpf

Related posts about xaml