使用HandyControl的TextBox封装一个选择路径的控件

使用HandyControl的TextBox封装一个选择路径的控件:


1.自定义一个SelectPathTextBox类继承自HandyControl中的TextBox,并添加一个选择路径按钮的依赖属性

提示:CommonOpenFileDialog 需要通过nuget安装 WindowsAPICodePack-Shell 才能使用

    public class SelectPathTextBox : TextBox
    {

        public static readonly DependencyProperty SelectPathCommandProperty = DependencyProperty.Register("SelectPathCommand", typeof(ICommand), typeof(SelectPathTextBox));

        private ICommand _selectPathCommand;
        public ICommand SelectPathCommand
        {
            get { return (ICommand)GetValue(SelectPathCommandProperty); }
            set { SetValue(SelectPathCommandProperty, value); }
        }


        public SelectPathTextBox()
        {
            SelectPathCommand = new DelegateCommand<object>((object obj) =>
            {
                string fullFileName = this.Text;

                CommonOpenFileDialog dialog = new CommonOpenFileDialog();
                dialog.InitialDirectory = fullFileName;
                dialog.IsFolderPicker = true;

                if (dialog.ShowDialog(GetTopWindow()) != CommonFileDialogResult.Ok)
                    return;

                fullFileName = dialog.FileName;

                SetCurrentValue(TextProperty, fullFileName);
            });
        }
		//获取Top窗口
		[DllImport("user32.dll")]
		static extern IntPtr GetActiveWindow();
		public static System.Windows.Window GetTopWindow()
		{
			var hwnd = GetActiveWindow();
		    if (hwnd == IntPtr.Zero)
		    	return Application.Current.MainWindow;
		   return GetWindowFromHwnd(hwnd);
		}
	
		private static System.Windows.Window GetWindowFromHwnd(IntPtr hwnd)
		{
			var fromHwnd = HwndSource.FromHwnd(hwnd);
			if (fromHwnd != null) 
				return (System.Windows.Window)fromHwnd.RootVisual;
			return null;
		}
    }
	
	

2.添加样式:

提示:TargetType需要指向上面自定义的类。Template中的Button 绑定到自定义类中的依赖属性

 xmlns:hc="https://handyorg.github.io/handycontrol"
 xmlns:control="clr-namespace:XXXXXXXXXX.Control"

 <Style x:Key="CustomTextBoxBaseStyle" TargetType="control:SelectPathTextBox">
        <Setter Property="MinHeight" Value="{StaticResource DefaultControlHeight}" />
        <Setter Property="Background" Value="{DynamicResource RegionBrush}" />
        <Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}" />
        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="CaretBrush" Value="{DynamicResource PrimaryTextBrush}" />
        <Setter Property="hc:BorderElement.CornerRadius" Value="{StaticResource DefaultCornerRadius}" />
        <Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="AllowDrop" Value="true" />
        <Setter Property="Padding" Value="{StaticResource DefaultInputPadding}" />
        <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
        <Setter Property="Stylus.IsFlicksEnabled" Value="False" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="control:SelectPathTextBox">
                    <Grid MinHeight="{Binding Path=(hc:InfoElement.MinContentHeight),RelativeSource={RelativeSource TemplatedParent}}" Height="{Binding Path=(hc:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="{Binding Path=(hc:InfoElement.TitleWidth),RelativeSource={RelativeSource TemplatedParent}}"/>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>
                        <DockPanel LastChildFill="True" Visibility="{Binding Path=(hc:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" VerticalAlignment="{Binding Path=(hc:TitleElement.VerticalAlignment),RelativeSource={RelativeSource TemplatedParent}}" Margin="0,7,6,7">
                            <TextBlock DockPanel.Dock="Left" hc:TextBlockAttach.AutoTooltip="True" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Text="{Binding Path=(hc:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
                            <ContentPresenter DockPanel.Dock="Left" TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(hc:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(hc:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
                        </DockPanel>
                        <Border x:Name="border" Grid.Column="1" Grid.ColumnSpan="2" CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
                        <TextBlock x:Name="Placeholder" Padding="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Grid.Column="1" Visibility="{TemplateBinding Text,Converter={StaticResource String2VisibilityReConverter}}" HorizontalAlignment="Stretch" Style="{StaticResource TextBlockDefaultThiLight}" Text="{Binding Path=(hc:InfoElement.Placeholder),RelativeSource={RelativeSource TemplatedParent}}"/>
                        <ScrollViewer Padding="{TemplateBinding Padding}" Margin="-1,1" Grid.Column="1" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                        <Button Grid.Column="2" HorizontalAlignment="Right" Command="{TemplateBinding SelectPathCommand}" Style="{StaticResource ButtonInfo}" hc:IconElement.Geometry="M912 208H427.872l-50.368-94.176A63.936 63.936 0 0 0 321.056 80H112c-35.296 0-64 28.704-64 64v736c0 35.296 28.704 64 64 64h800c35.296 0 64-28.704 64-64v-608c0-35.296-28.704-64-64-64z m-800-64h209.056l68.448 128H912v97.984c-0.416 0-0.8-0.128-1.216-0.128H113.248c-0.416 0-0.8 0.128-1.248 0.128V144z m0 736v-96l1.248-350.144 798.752 1.216V784h0.064v96H112z" Background="#059491"/>
                    </Grid>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Opacity" TargetName="border" Value="0.4" />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource SecondaryBorderBrush}" />
                        </Trigger>
                        <Trigger Property="IsFocused" Value="true">
                            <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource PrimaryBrush}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

3.使用:

xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:control="clr-namespace:XXXXXXX.Control"

<control:SelectPathTextBox hc:InfoElement.TitleWidth="120"
                           hc:InfoElement.Placeholder="路径" 
                           hc:InfoElement.TitlePlacement="Left" 
                           hc:InfoElement.Title="路径"
                           hc:InfoElement.Necessary="True" 
                           hc:InfoElement.Symbol="●"
                           Text="{Binding Path, Mode=TwoWay}"
                           Style="{StaticResource CustomTextBoxBaseStyle}" 
                           VerticalAlignment="Center"/>

4.效果

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值