翼度科技»论坛 编程开发 .net 查看内容

WPF --- 非Button自定义控件实现点击功能

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
引言

今天在做一个设置文件夹路径的功能,就是一个文本框,加个按钮,点击按钮,弹出 FolderBrowserDialog 再选择文件夹路径,简单做法,可以直接 StackPanel 横向放置一个 TextBox 和一个 Image Button,然后点击按钮在 后台代码中给 ViewModel 的 FilePath赋值。但是这样属实不够优雅,UI 不够优雅,代码实现也可谓是强耦合,那接下来我分享一下我的实现方案。
目标

做这个设置文件夹路径的功能,我的目标是点击任何地方都可以打开 FolderBrowserDialog,那就需要把文本框,按钮作为一个整体控件,且选择完文件夹路径后就给绑定的 ViewModel 的 FilePath 赋值。
准备工作

首先,既然要设计一个整体控件,那么 UI 如下:

接下来创建这个整体的控件,不使用 Button ,直接使用 Control,来创建自定义控件 OpenFolderBrowserControl :
Code Behind 代码如下:
  1. public class OpenFolderBrowserControl : Control,
  2. {
  3.     static OpenFolderBrowserControl()
  4.     {
  5.         DefaultStyleKeyProperty.OverrideMetadata(typeof(OpenFolderBrowserControl), new FrameworkPropertyMetadata(typeof(OpenFolderBrowserControl)));
  6.     }
  7.     public static readonly DependencyProperty FilePathProperty = DependencyProperty.Register("FilePath", typeof(string), typeof(OpenFolderBrowserControl));
  8.     [Description("文件路径")]
  9.     public string FilePath
  10.     {
  11.         get => (string)GetValue(FilePathProperty);
  12.         set => SetValue(FilePathProperty, value);
  13.     }
  14. }
复制代码
Themes/Generic.xaml 中的设计代码如下:
  1.                                 </TextBox.Style>
  2.                             </TextBox>
  3.                             <Border
  4.                                 Height="56"
  5.                                 Margin="-60,0,0,0"
  6.                                 Background="White"
  7.                                 BorderBrush="#CAD2DD"
  8.                                 BorderThickness="2"
  9.                                 CornerRadius="0,8,8,0">
  10.                                 <StackPanel
  11. <Grid>
  12.     <Grid.ColumnDefinitions>
  13.         <ColumnDefinition Width="1*" />
  14.         <ColumnDefinition Width="2*" />
  15.     </Grid.ColumnDefinitions>
  16.    
  17.     <TextBlock
  18.         HorizontalAlignment="Center"
  19.         VerticalAlignment="Center"
  20.         FontSize="22"
  21.         Text="设置文件路径:" />
  22.     <local:OpenFolderBrowserControl
  23.         Grid.Column="1"
  24.         HorizontalAlignment="Left"
  25.         Click="OpenFolderBrowserControl_Click"
  26.         Command="{Binding ClickCommand}"
  27.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  28. </Grid>HorizontalAlignment="Center"
  29. <Grid>
  30.     <Grid.ColumnDefinitions>
  31.         <ColumnDefinition Width="1*" />
  32.         <ColumnDefinition Width="2*" />
  33.     </Grid.ColumnDefinitions>
  34.    
  35.     <TextBlock
  36.         HorizontalAlignment="Center"
  37.         VerticalAlignment="Center"
  38.         FontSize="22"
  39.         Text="设置文件路径:" />
  40.     <local:OpenFolderBrowserControl
  41.         Grid.Column="1"
  42.         HorizontalAlignment="Left"
  43.         Click="OpenFolderBrowserControl_Click"
  44.         Command="{Binding ClickCommand}"
  45.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  46. </Grid>VerticalAlignment="Center"
  47. <Grid>
  48.     <Grid.ColumnDefinitions>
  49.         <ColumnDefinition Width="1*" />
  50.         <ColumnDefinition Width="2*" />
  51.     </Grid.ColumnDefinitions>
  52.    
  53.     <TextBlock
  54.         HorizontalAlignment="Center"
  55.         VerticalAlignment="Center"
  56.         FontSize="22"
  57.         Text="设置文件路径:" />
  58.     <local:OpenFolderBrowserControl
  59.         Grid.Column="1"
  60.         HorizontalAlignment="Left"
  61.         Click="OpenFolderBrowserControl_Click"
  62.         Command="{Binding ClickCommand}"
  63.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  64. </Grid>Orientation="Horizontal">
  65. <Grid>
  66.     <Grid.ColumnDefinitions>
  67.         <ColumnDefinition Width="1*" />
  68.         <ColumnDefinition Width="2*" />
  69.     </Grid.ColumnDefinitions>
  70.    
  71.     <TextBlock
  72.         HorizontalAlignment="Center"
  73.         VerticalAlignment="Center"
  74.         FontSize="22"
  75.         Text="设置文件路径:" />
  76.     <local:OpenFolderBrowserControl
  77.         Grid.Column="1"
  78.         HorizontalAlignment="Left"
  79.         Click="OpenFolderBrowserControl_Click"
  80.         Command="{Binding ClickCommand}"
  81.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  82. </Grid><Ellipse
  83. <Grid>
  84.     <Grid.ColumnDefinitions>
  85.         <ColumnDefinition Width="1*" />
  86.         <ColumnDefinition Width="2*" />
  87.     </Grid.ColumnDefinitions>
  88.    
  89.     <TextBlock
  90.         HorizontalAlignment="Center"
  91.         VerticalAlignment="Center"
  92.         FontSize="22"
  93.         Text="设置文件路径:" />
  94.     <local:OpenFolderBrowserControl
  95.         Grid.Column="1"
  96.         HorizontalAlignment="Left"
  97.         Click="OpenFolderBrowserControl_Click"
  98.         Command="{Binding ClickCommand}"
  99.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  100. </Grid>    Width="5"
  101. <Grid>
  102.     <Grid.ColumnDefinitions>
  103.         <ColumnDefinition Width="1*" />
  104.         <ColumnDefinition Width="2*" />
  105.     </Grid.ColumnDefinitions>
  106.    
  107.     <TextBlock
  108.         HorizontalAlignment="Center"
  109.         VerticalAlignment="Center"
  110.         FontSize="22"
  111.         Text="设置文件路径:" />
  112.     <local:OpenFolderBrowserControl
  113.         Grid.Column="1"
  114.         HorizontalAlignment="Left"
  115.         Click="OpenFolderBrowserControl_Click"
  116.         Command="{Binding ClickCommand}"
  117.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  118. </Grid>    Height="5"
  119. <Grid>
  120.     <Grid.ColumnDefinitions>
  121.         <ColumnDefinition Width="1*" />
  122.         <ColumnDefinition Width="2*" />
  123.     </Grid.ColumnDefinitions>
  124.    
  125.     <TextBlock
  126.         HorizontalAlignment="Center"
  127.         VerticalAlignment="Center"
  128.         FontSize="22"
  129.         Text="设置文件路径:" />
  130.     <local:OpenFolderBrowserControl
  131.         Grid.Column="1"
  132.         HorizontalAlignment="Left"
  133.         Click="OpenFolderBrowserControl_Click"
  134.         Command="{Binding ClickCommand}"
  135.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  136. </Grid>    Margin="3"
  137. <Grid>
  138.     <Grid.ColumnDefinitions>
  139.         <ColumnDefinition Width="1*" />
  140.         <ColumnDefinition Width="2*" />
  141.     </Grid.ColumnDefinitions>
  142.    
  143.     <TextBlock
  144.         HorizontalAlignment="Center"
  145.         VerticalAlignment="Center"
  146.         FontSize="22"
  147.         Text="设置文件路径:" />
  148.     <local:OpenFolderBrowserControl
  149.         Grid.Column="1"
  150.         HorizontalAlignment="Left"
  151.         Click="OpenFolderBrowserControl_Click"
  152.         Command="{Binding ClickCommand}"
  153.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  154. </Grid>    Fill="#949494" />
  155. <Grid>
  156.     <Grid.ColumnDefinitions>
  157.         <ColumnDefinition Width="1*" />
  158.         <ColumnDefinition Width="2*" />
  159.     </Grid.ColumnDefinitions>
  160.    
  161.     <TextBlock
  162.         HorizontalAlignment="Center"
  163.         VerticalAlignment="Center"
  164.         FontSize="22"
  165.         Text="设置文件路径:" />
  166.     <local:OpenFolderBrowserControl
  167.         Grid.Column="1"
  168.         HorizontalAlignment="Left"
  169.         Click="OpenFolderBrowserControl_Click"
  170.         Command="{Binding ClickCommand}"
  171.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  172. </Grid><Ellipse
  173. <Grid>
  174.     <Grid.ColumnDefinitions>
  175.         <ColumnDefinition Width="1*" />
  176.         <ColumnDefinition Width="2*" />
  177.     </Grid.ColumnDefinitions>
  178.    
  179.     <TextBlock
  180.         HorizontalAlignment="Center"
  181.         VerticalAlignment="Center"
  182.         FontSize="22"
  183.         Text="设置文件路径:" />
  184.     <local:OpenFolderBrowserControl
  185.         Grid.Column="1"
  186.         HorizontalAlignment="Left"
  187.         Click="OpenFolderBrowserControl_Click"
  188.         Command="{Binding ClickCommand}"
  189.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  190. </Grid>    Width="5"
  191. <Grid>
  192.     <Grid.ColumnDefinitions>
  193.         <ColumnDefinition Width="1*" />
  194.         <ColumnDefinition Width="2*" />
  195.     </Grid.ColumnDefinitions>
  196.    
  197.     <TextBlock
  198.         HorizontalAlignment="Center"
  199.         VerticalAlignment="Center"
  200.         FontSize="22"
  201.         Text="设置文件路径:" />
  202.     <local:OpenFolderBrowserControl
  203.         Grid.Column="1"
  204.         HorizontalAlignment="Left"
  205.         Click="OpenFolderBrowserControl_Click"
  206.         Command="{Binding ClickCommand}"
  207.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  208. </Grid>    Height="5"
  209. <Grid>
  210.     <Grid.ColumnDefinitions>
  211.         <ColumnDefinition Width="1*" />
  212.         <ColumnDefinition Width="2*" />
  213.     </Grid.ColumnDefinitions>
  214.    
  215.     <TextBlock
  216.         HorizontalAlignment="Center"
  217.         VerticalAlignment="Center"
  218.         FontSize="22"
  219.         Text="设置文件路径:" />
  220.     <local:OpenFolderBrowserControl
  221.         Grid.Column="1"
  222.         HorizontalAlignment="Left"
  223.         Click="OpenFolderBrowserControl_Click"
  224.         Command="{Binding ClickCommand}"
  225.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  226. </Grid>    Margin="3"
  227. <Grid>
  228.     <Grid.ColumnDefinitions>
  229.         <ColumnDefinition Width="1*" />
  230.         <ColumnDefinition Width="2*" />
  231.     </Grid.ColumnDefinitions>
  232.    
  233.     <TextBlock
  234.         HorizontalAlignment="Center"
  235.         VerticalAlignment="Center"
  236.         FontSize="22"
  237.         Text="设置文件路径:" />
  238.     <local:OpenFolderBrowserControl
  239.         Grid.Column="1"
  240.         HorizontalAlignment="Left"
  241.         Click="OpenFolderBrowserControl_Click"
  242.         Command="{Binding ClickCommand}"
  243.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  244. </Grid>    Fill="#949494" />
  245. <Grid>
  246.     <Grid.ColumnDefinitions>
  247.         <ColumnDefinition Width="1*" />
  248.         <ColumnDefinition Width="2*" />
  249.     </Grid.ColumnDefinitions>
  250.    
  251.     <TextBlock
  252.         HorizontalAlignment="Center"
  253.         VerticalAlignment="Center"
  254.         FontSize="22"
  255.         Text="设置文件路径:" />
  256.     <local:OpenFolderBrowserControl
  257.         Grid.Column="1"
  258.         HorizontalAlignment="Left"
  259.         Click="OpenFolderBrowserControl_Click"
  260.         Command="{Binding ClickCommand}"
  261.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  262. </Grid><Ellipse
  263. <Grid>
  264.     <Grid.ColumnDefinitions>
  265.         <ColumnDefinition Width="1*" />
  266.         <ColumnDefinition Width="2*" />
  267.     </Grid.ColumnDefinitions>
  268.    
  269.     <TextBlock
  270.         HorizontalAlignment="Center"
  271.         VerticalAlignment="Center"
  272.         FontSize="22"
  273.         Text="设置文件路径:" />
  274.     <local:OpenFolderBrowserControl
  275.         Grid.Column="1"
  276.         HorizontalAlignment="Left"
  277.         Click="OpenFolderBrowserControl_Click"
  278.         Command="{Binding ClickCommand}"
  279.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  280. </Grid>    Width="5"
  281. <Grid>
  282.     <Grid.ColumnDefinitions>
  283.         <ColumnDefinition Width="1*" />
  284.         <ColumnDefinition Width="2*" />
  285.     </Grid.ColumnDefinitions>
  286.    
  287.     <TextBlock
  288.         HorizontalAlignment="Center"
  289.         VerticalAlignment="Center"
  290.         FontSize="22"
  291.         Text="设置文件路径:" />
  292.     <local:OpenFolderBrowserControl
  293.         Grid.Column="1"
  294.         HorizontalAlignment="Left"
  295.         Click="OpenFolderBrowserControl_Click"
  296.         Command="{Binding ClickCommand}"
  297.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  298. </Grid>    Height="5"
  299. <Grid>
  300.     <Grid.ColumnDefinitions>
  301.         <ColumnDefinition Width="1*" />
  302.         <ColumnDefinition Width="2*" />
  303.     </Grid.ColumnDefinitions>
  304.    
  305.     <TextBlock
  306.         HorizontalAlignment="Center"
  307.         VerticalAlignment="Center"
  308.         FontSize="22"
  309.         Text="设置文件路径:" />
  310.     <local:OpenFolderBrowserControl
  311.         Grid.Column="1"
  312.         HorizontalAlignment="Left"
  313.         Click="OpenFolderBrowserControl_Click"
  314.         Command="{Binding ClickCommand}"
  315.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  316. </Grid>    Margin="3"
  317. <Grid>
  318.     <Grid.ColumnDefinitions>
  319.         <ColumnDefinition Width="1*" />
  320.         <ColumnDefinition Width="2*" />
  321.     </Grid.ColumnDefinitions>
  322.    
  323.     <TextBlock
  324.         HorizontalAlignment="Center"
  325.         VerticalAlignment="Center"
  326.         FontSize="22"
  327.         Text="设置文件路径:" />
  328.     <local:OpenFolderBrowserControl
  329.         Grid.Column="1"
  330.         HorizontalAlignment="Left"
  331.         Click="OpenFolderBrowserControl_Click"
  332.         Command="{Binding ClickCommand}"
  333.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  334. </Grid>    Fill="#949494" />
  335.                                 </StackPanel>
  336.                             </Border>
  337.                         </StackPanel>
  338.                     </Border>
  339.                 </ControlTemplate>
  340.             </Setter.Value>
  341.         </Setter>
  342.     </Style>
复制代码
这样创建的控件实际上是没有点击功能的。
那么接下来看一下点击功能方案实现。
点击功能方案实现

因为有 MVVM 的存在,所以在 WPF 中 Button 点击功能有两种方案,

  • 第一种是直接注册点击事件,比如 Click="OpenFolderBrowserControl_Click"
  • 第二种是绑定Command、CommandParameter、CommandTarget,比如 Command="{Binding ClickCommand}" CommandParameter="" CommandTarget="" 。
但是上文中我们定义的是一个 Control ,它既没有 Click 也没有 Command,所以,我们需要给 OpenFolderBrowserControl 定义Click 和 Command。
定义点击事件

定义点击事件比较简单,直接声明一个 RoutedEventHandler ,命名为 Click 就可以了。
  1. public event RoutedEventHandler? Click;
复制代码
定义Command

定义 Command 就需要 ICommandSource 接口,重点介绍一下 ICommandSource 接口。
ICommandSource 接口用于指示控件可以生成和执行命令。该接口定义了三个成员

  • 定义了一个 ICommand 类型的属性 Command,
  • 定义了一个表示与控件关联的, IInputElement 类型的 CommandTarget
  • 定义了一个表示命令参数,object 类型的属性 CommandParameter
上述两段的定义如下:
  1. public class OpenFolderBrowserControl : Control, ICommandSource
  2. {
  3.     //上文中已有代码此处省略...
  4.     #region 定义点击事件
  5.     public event RoutedEventHandler? Click;
  6.     #endregion
  7.     #region 定义command
  8.     public static readonly DependencyProperty CommandProperty =
  9.         DependencyProperty.Register("Command", typeof(ICommand), typeof(OpenFolderBrowserControl), new UIPropertyMetadata(null))
  10.     public ICommand Command
  11.     {
  12.         get { return (ICommand)GetValue(CommandProperty); }
  13.         set { SetValue(CommandProperty, value); }
  14.     }
  15.     public object CommandParameter
  16.     {
  17.         get { return (object)GetValue(CommandParameterProperty); }
  18.         set { SetValue(CommandParameterProperty, value); }
  19.     }
  20.     public static readonly DependencyProperty CommandParameterProperty =
  21.         DependencyProperty.Register("CommandParameter", typeof(object), typeof(OpenFolderBrowserControl));
  22.     public IInputElement CommandTarget
  23.     {
  24.         get { return (IInputElement)GetValue(CommandTargetProperty); }
  25.         set { SetValue(CommandTargetProperty, value); }
  26.     }
  27.     public static readonly DependencyProperty CommandTargetProperty =
  28.         DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(OpenFolderBrowserControl));
复制代码
实现点击功能

好了,到此为止我仅定义好了点击事件和 Command,但是并没有能够触发这两个功能的地方。
既然是要实现点击功能,那最直观的方法就是 OnMouseLeftButtonUp,该方法是 WPF 核心基类 UIElement的虚方法,我们可以直接重写。如下代码:
  1. public class OpenFolderBrowserControl : Control, ICommandSource
  2. {
  3.     //上文中已有代码此处省略...
  4.    
  5.     protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
  6.     {
  7.         base.OnMouseLeftButtonUp(e);
  8.         //调用点击事件
  9.         Click?.Invoke(e.Source, e);
  10.         //调用Command
  11.         ICommand command = Command;
  12.         object parameter = CommandParameter;
  13.         IInputElement target = CommandTarget;
  14.         RoutedCommand routedCmd = command as RoutedCommand;
  15.         if (routedCmd != null && routedCmd.CanExecute(parameter, target))
  16.         {
  17.             routedCmd.Execute(parameter, target);
  18.         }
  19.         else if (command != null && command.CanExecute(parameter))
  20.         {
  21.             command.Execute(parameter);
  22.         }
  23.     }
  24. }
复制代码
到此位置,我们的非Button自定义控件实现点击的需求就完成了,接下来测试一下。
测试

准备测试窗体和 ViewModel,这里为了不引入依赖包,也算是复习一下 MVVM 的实现,就手动实现 ICommand 和 INotifyPropertyChanged。
ICommand 实现:
  1. public class RelayCommand : ICommand
  2. {
  3.     private readonly Action? _execute;
  4.     public RelayCommand(Action? execute)
  5.     {
  6.         _execute = execute;
  7.     }
  8.     public bool CanExecute(object? parameter)
  9.     {
  10.         return true;
  11.     }
  12.     public void Execute(object? parameter)
  13.     {
  14.         _execute?.Invoke();
  15.     }
  16.     public event EventHandler? CanExecuteChanged;
  17. }
复制代码
TestViewModel 实现:
这里的 ClickCommand 触发之后,我输出了当前 FilePath的值。
  1. public class TestViewModel : INotifyPropertyChanged
  2. {
  3.     public TestViewModel()
  4.     {
  5.         FilePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
  6.     }
  7.     public event PropertyChangedEventHandler? PropertyChanged;
  8.    
  9.     protected virtual void OnPropertyChanged(string propertyName)
  10.     {
  11.         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  12.     }
  13.     private string filePath = string.Empty;
  14.     /// <summary>
  15.     /// 文件路径
  16.     /// </summary>
  17.     public string FilePath
  18.     {
  19.         get { return filePath; }
  20.         set { filePath = value; OnPropertyChanged(nameof(FilePath)); }
  21.     }
  22.     private ICommand clickCommand = null;
  23.     /// <summary>
  24.     /// 点击事件
  25.     /// </summary>
  26.     public ICommand ClickCommand
  27.     {
  28.         get { return clickCommand ??= new RelayCommand(Click); }
  29.         set { clickCommand = value; }
  30.     }
  31.     private void Click()
  32.     {
  33.         MessageBox.Show($"ViewModel Clicked!The value of FilePath is {FilePath}");
  34.     }
  35. }
复制代码
窗体UI代码
  1. <Grid>
  2.     <Grid.ColumnDefinitions>
  3.         <ColumnDefinition Width="1*" />
  4.         <ColumnDefinition Width="2*" />
  5.     </Grid.ColumnDefinitions>
  6.    
  7.     <TextBlock
  8.         HorizontalAlignment="Center"
  9.         VerticalAlignment="Center"
  10.         FontSize="22"
  11.         Text="设置文件路径:" />
  12.     <local:OpenFolderBrowserControl
  13.         Grid.Column="1"
  14.         HorizontalAlignment="Left"
  15.         Click="OpenFolderBrowserControl_Click"
  16.         Command="{Binding ClickCommand}"
  17.         FilePath="{Binding FilePath, Mode=TwoWay}" />
  18. </Grid>
复制代码
窗体 Code Behind 代码
  1. public partial class MainWindow : Window
  2. {
  3.     public MainWindow()
  4.     {
  5.         InitializeComponent();
  6.         DataContext = new TestViewModel();
  7.     }
  8.     private void OpenFolderBrowserControl_Click(object sender, RoutedEventArgs e)
  9.     {
  10.         FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
  11.         DialogResult result = folderBrowserDialog.ShowDialog();
  12.         if (result == System.Windows.Forms.DialogResult.OK)
  13.         {
  14.             string selectedFolderPath = folderBrowserDialog.SelectedPath;
  15.             var Target = sender as OpenFolderBrowserControl;
  16.             if (Target != null)
  17.             {
  18.                 Target.FilePath = selectedFolderPath;
  19.             }
  20.         }
  21.     }
  22. }
复制代码
测试结果
我点击整个控件的任意地方,都能打开文件夹浏览器。

选择音乐文件夹后,弹窗提示 ViewModel Clicked!The value of FilePath is C:\Users\Administrator\Music

结论

从测试结果中可以看出,在 UI 注册的 ClickCommand 均触发。这个方案仅仅是抛砖引玉,只要任意控件(非button)需要实现点击功能,都可以这样去实现。
实现核心就是两个方案:

  • 直接定义点击事件。
  • 实现ICommandSource。
然后再重写各种鼠标事件,鼠标按下,鼠标抬起,双击等都可以实现。
上述方案既保证了 UI 的优雅也保证了 MVVM 架构的前后分离特性。
如果大家有更好更优雅的方案,欢迎留言讨论。

来源:https://www.cnblogs.com/pandefu/archive/2023/08/17/17638683.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具