Avalonia TemplatedControl (模板控件) 自定义控件

在ava中的模板控件相当于wpf中的自定义控件

可以在新建模版中选择Avalonia TemplatedControl会自动生成axaml和cs配置文件

在下面示例中,将绘制一个文本框和一个按钮,用来组合一个搜索控件

xaml代码

  • 在 ControlTheme 中定义布局
  • 在 Style 中调节样式
  • Text="{TemplateBinding SearchText,Mode=TwoWay}" 用于将外部传入的SearchText设置到内部的文本框
    image
<ResourceDictionary xmlns="https://github.com/avaloniaui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:primitives="using:Avalonia.Controls.Primitives"
                    xmlns:controls="using:MyCustomControl">

   <Design.PreviewWith>
      <StackPanel Width="250" Spacing="10">
         <StackPanel Background="{DynamicResource SystemRegionBrush}">
            <controls:SearchTextBox />
         </StackPanel>
      </StackPanel>
   </Design.PreviewWith>

   <ControlTheme x:Key="{x:Type controls:SearchTextBox}"
                 TargetType="controls:SearchTextBox">
      <Setter Property="Template">
         <ControlTemplate>
            <StackPanel Height="35" Orientation="Horizontal">
               <TextBox Height="26" x:Name="tbText" Width="120" Text="{TemplateBinding SearchText,Mode=TwoWay}"
                        AcceptsReturn="False">
               </TextBox>
               <Button Focusable="False"
                       Width="60" x:Name="btnSearch" Content="搜索">
               </Button>
            </StackPanel>
         </ControlTemplate>
      </Setter>

      <Style Selector="^ /template/ Button">
         <Setter Property="Background" Value="DodgerBlue" />
         <Setter Property="Foreground" Value="White" />
      </Style>

   </ControlTheme>

</ResourceDictionary>

定义后台代码

  • Submit事件用于在外部赋值传递到内部控件事件中执行
public class SearchTextBox : TemplatedControl
{
   public SearchTextBox()
   {
      // 允许控件获取焦点
      Focusable = true;
   }

   Button btnSearch;
   TextBox tbText;

   protected override void OnGotFocus(FocusChangedEventArgs e)
   {
      base.OnGotFocus(e);
      tbText.Focus();
   }

   public static readonly StyledProperty<string> SearchTextProperty =
        AvaloniaProperty.Register<SearchTextBox, string>(nameof(SearchText), defaultValue: "");

   public string SearchText
   {
      get => GetValue(SearchTextProperty);
      set => SetValue(SearchTextProperty, value);
   }

   protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
   {
      base.OnApplyTemplate(e);
      
      //根据模板内的名字找到控件
      btnSearch = e.NameScope.Find<Button>("btnSearch")!;
      tbText = e.NameScope.Find<TextBox>("tbText")!;
      btnSearch.Click += (s, e) =>
      {
         //在内部按钮的事件中,执行外部注册的 OnSearch 事件 
         RaiseEvent(new RoutedEventArgs(SubmitEvent));
      };
      tbText.KeyUp += (s, e) =>
      {
         if (e.Key == Avalonia.Input.Key.Enter)
         {
            RaiseEvent(new RoutedEventArgs(SubmitEvent));
         }
      };
   }


   public static readonly RoutedEvent<RoutedEventArgs> SubmitEvent =
    RoutedEvent.Register<SearchTextBox, RoutedEventArgs>(nameof(Submit), RoutingStrategies.Direct);

   public event EventHandler<RoutedEventArgs> Submit
   {
      add => AddHandler(SubmitEvent, value);
      remove => RemoveHandler(SubmitEvent, value);
   }
}

在app.axaml中合并引入控件

 <Application.Resources>
      <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
              <ResourceInclude Source="avares://MyCustomControl/SearchTextBox.axaml" />
          </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
  </Application.Resources>

在页面上引用和使用

 xmlns:c="using:MyCustomControl"

 <c:SearchTextBox SearchText="百度一下"></c:SearchTextBox>
posted @ 2024-01-19 20:03  trykle  阅读(897)  评论(0)    收藏  举报