C# WPF无外观控制事件

C# WPF无外观控制事件,c#,wpf,xaml,C#,Wpf,Xaml,我有以下课程: public class LooklessControl : Control { public List<int> IntList { get; private set; } public int CurrentInt { get; private set; } private int _index = 0; static LooklessControl() { DefaultStyleKeyProperty

我有以下课程:

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();
    }
}
public类LooklessControl:Control
{
公共列表IntList{get;private set;}
public int CurrentInt{get;private set;}
私有int_指数=0;
静态LooklessControl()
{
OverrideMetadata(typeof(LooklessControl),new FrameworkPropertyMetadata(typeof(LooklessControl));
}
公共LooklessControl()
{
IntList=新列表();
对于(int i=0;i<10;i++)
{
添加(i);
}
CurrentInt=IntList[_index];
}
公共静态只读路由命令NextItemCommand=
新的RoutedCommand(“NextItemCommand”,typeof(LooklessControl));
私有void ExecutedNextItemCommand(对象发送方,ExecutedRoutedEventArgs e)
{
NextItemHandler();
}
私有void CanExecuteNextItemCommand(对象发送方,CanExecuteRouteEventArgs e)
{
e、 CanExecute=true;
}
公共静态只读路由命令PreviItemCommand=
新RoutedCommand(“PrevItemCommand”,typeof(LooklessControl));
私有void ExecutedPrevItemCommand(ExecutedRoutedEventArgs e)
{
previItemHandler();
}
私有void CanExecutePrevItemCommand(对象发送方,CanExecuteRouteEventArgs e)
{
e、 CanExecute=true;
}
公共静态只读RoutedEvent NextItemEvent=
RegisterRoutedEvent(“NextItemEvent”,RoutingStrategy.Bubble,typeof(RoutedEventHandler),typeof(LooklessControl));
公共活动路线Deventhandler NextItem
{
添加{AddHandler(NextItemEvent,value);}
remove{RemoveHandler(NextItemEvent,value);}
}
私有void RaiseNextItemEvent()
{
RoutedEventArgs=新的RoutedEventArgs(LooklessControl.NextItemEvent);
RaiseEvent(args);
}
公共静态只读RoutedEvent PreviItemEvent=
RegisterRoutedEvent(“PreviItemEvent”,RoutingStrategy.Bubble,typeof(RoutedEventHandler),typeof(LooklessControl));
公共活动路线EventHandler Previitem
{
添加{AddHandler(PreviItemEvent,value);}
删除{RemoveHandler(PreviItemEvent,value);}
}
私有void RaisePrevItemEvent()
{
RoutedEventArgs args=新的RoutedEventArgs(LooklessControl.PreviItemEvent);
RaiseEvent(args);
}
私有void NextItemHandler()
{
_索引++;
if(_index==IntList.Count)
{
_指数=0;
}
CurrentInt=IntList[_index];
RaiseNextItemEvent();
}
private void PrevItemHandler()
{
_索引--;
如果(_index==0)
{
_index=IntList.Count-1;
}
CurrentInt=IntList[_index];
RaisePrevItemEvent();
}
}
该类的默认样式为Generic.xaml,如下所示:

<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>

如何使用户在单击pathLeftArrow时触发LooklessControl.PreviItemCommand,或单击pathRightArrow时触发LooklessControl.NextItemCommand,或单击列表框中的某个项目时通知LooklessControl新选择的项目

换句话说,如果不将x:Class添加到Generic.xaml的顶部,从而为其创建代码隐藏文件(我假设您不想这样做),那么如何处理xaml中没有命令属性(按钮之外的所有内容)的元素的事件


LooklessControl是否应该有自己的XAML文件(与创建新UserControl时得到的文件非常相似),Generic.XAML只是作为MergedActionAR作为默认模板拉入?或者有没有其他公认的方法来完成我的任务?

回答您的最后一个问题:没有。无外观控件不需要任何已知的XAML。这就是lookless的意思

这里有两个选项,但我建议您使用基本为空的控件模板将元素包装在按钮中:

<ControlTemplate x:Key="contentOnlyButton" TargetType="{x:Type Button}">
    <ContentPresenter />
</ControlTemplate>

...

   <Button Grid.Column="0" Template="{StaticResource contentOnlyButton}"
           Command="{x:Static local:LooklessControl.PrevItemCommand}">
       <Path x:Name="pathLeftArrow" Data="M0,0.5 L1,1 1,0Z" Width="6" Height="14" 
             Stretch="Fill" HorizontalAlignment="Center" Fill="SlateBlue"/>
   </Button>
这样做需要注意的一点是,不需要模板来定义您要查找的部件,因此您需要优雅地检查这种情况。在此处抛出
NullReferenceExceptions
将使控件的重新序列化成为意外删除所需元素的设计人员/开发人员的一大难题。您还需要遵循标准实践,使用PART_uu语法命名所需元素,并使用
TemplatePart
属性装饰类

[TemplatePart(Name = "PART_PathLeftArrow", Type = typeof(UIElement))]
[TemplatePart(Name = "PART_PathRightArrow", Type = typeof(UIElement))]
...
public class LooklessControl : Control
编辑:为了使按钮对单击做出响应,您需要为您已经定义的函数设置CommandBinding。您可以将其作为类命令绑定执行,如下所示:

static LooklessControl()
{
    CommandManager.RegisterClassCommandBinding(
        typeof(LooklessControl),
        new CommandBinding(NextItemCommand, ExecutedNextItemCommand, CanExecuteNextItemCommand));

    CommandManager.RegisterClassCommandBinding(
        typeof(LooklessControl),
        new CommandBinding(PrevItemCommand, ExecutedPrevItemCommand, CanExecutePrevItemCommand));
}

执行类命令绑定的原因是,如果将其添加到控件的CommandBindings集合中,使用控件的人可能会无意中删除它们。还记得更新命令处理方法,使其具有静态语义。

+1用于按钮。滚动条也是这样做的。看,我同意,按钮的想法似乎是最好的途径。当我按照上面的建议连接它们时,我得到了一个不再点击的按钮。当我删除Command属性时,按钮会单击(但显然不会执行任何操作),当我将Command属性重新放入时,如下所示:
static LooklessControl()
{
    CommandManager.RegisterClassCommandBinding(
        typeof(LooklessControl),
        new CommandBinding(NextItemCommand, ExecutedNextItemCommand, CanExecuteNextItemCommand));

    CommandManager.RegisterClassCommandBinding(
        typeof(LooklessControl),
        new CommandBinding(PrevItemCommand, ExecutedPrevItemCommand, CanExecutePrevItemCommand));
}