0

Silicon Labs SDK を使用するプロジェクトに取り組んでいます。SDK のラッパーを作成した後、SDK からの結果の一部を視覚化する WPF プロジェクトを作成しました。私の最初のテストは、GetNumDevices 関数を使用したものでした。私の WPF の知識はそれほど強力ではないので、目を充血させて申し訳ありませんが、デモンストレーションのために私が持っているものをお見せしましょう。まず、私が話している API メソッドについてです。

[DllImport("CP210xManufacturing.dll", CallingConvention = CallingConvention.StdCall)]
public static extern CP210x_STATUS CP210x_GetNumDevices(ref int lpdwNumDevices);

このメソッドを視覚化するために 2 つのラベルと 1 つのボタンを作成する代わりに、ユーザー コントロールを作成することにしました。

CP210UserControl.xaml

<UserControl x:Class="SiliconLabsRosettaStone.CP210UserControl"
             x:Name="panel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="300"
             DataContext="{Binding ElementName=panel}">
    <Border BorderBrush="DarkGreen" BorderThickness="3" Margin="2">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
                <ColumnDefinition Width="75"/>
            </Grid.ColumnDefinitions>

            <TextBlock Text="{Binding Caption}" Margin="3,0" />
            <Border Grid.Column="1" BorderBrush="Black" BorderThickness="2" Margin="3,0">
                <TextBlock x:Name="responseTextBlock" Text="{Binding Response}" />
            </Border>
            <Button Grid.Column="2" Content="Execute" Click="Button_Click" Margin="3,0" />
        </Grid>
    </Border>
</UserControl>

CP210UserControl.xaml.cs

public partial class CP210UserControl : UserControl
{
    public CP210UserControl()
    {
        InitializeComponent();
    }
    public void SetupUserControl(Func<CP210UserControl, CP210x_STATUS> function)
    {
        this.cp210Function = function;
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        CP210x_STATUS response = cp210Function(this);
        this.responseTextBlock.Background = response == CP210x_STATUS.CP210x_SUCCESS ? null : new SolidColorBrush(Colors.Pink);
    }

    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }

    public string Response
    {
        get { return (string)GetValue(ResponseProperty); }
        set { SetValue(ResponseProperty, value); }
    }

    public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(CP210UserControl), new PropertyMetadata("CP210x"));
    public static readonly DependencyProperty ResponseProperty = DependencyProperty.Register("Response", typeof(string), typeof(CP210UserControl), new PropertyMetadata(""));

    private Func<CP210UserControl, CP210x_STATUS> cp210Function;
}

それは、その使用法について質問があるファイルです。

これが私のメインウィンドウでの使用方法です

MainWindow.xaml

<StackPanel>
    <local:CP210UserControl x:Name="cpGetNumDevices" Grid.Row="1" Grid.ColumnSpan="3" Caption="CP210x_GetNumDevices" />
</StackPanel>

今、私が嫌いな部分について。接続方法:/

MainWindow.xaml.cs

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        cpGetNumDevices.SetupUserControl(getNumberDevices);
    }
    private CP210x_STATUS getNumberDevices(CP210UserControl control)
    {
        int devices = 0;
        var result = CP210xWrapper.CP210x_GetNumDevices(ref devices);
        control.Response = string.Format("Number Of Devices:{0}", devices);
        return result;
    }

xamlを次のようにすることができると思います

    <local:CP210UserControl x:Name="cpGetNumDevices" Grid.Row="1" Grid.ColumnSpan="3" Caption="CP210x_GetNumDevices" cp210Function="getNumberDevices" />

ユーザーコントロールをこれに変更した場合。

    public Func<CP210UserControl, CP210x_STATUS> cp210Function
    {
        get { return (Func<CP210UserControl, CP210x_STATUS>)GetValue(cp210FunctionProperty); }
        set { SetValue(cp210FunctionProperty, value); }
    }

    public static readonly DependencyProperty cp210FunctionProperty = DependencyProperty.Register("cp210Function", typeof(Func<CP210UserControl, CP210x_STATUS>), typeof(CP210UserControl), new PropertyMetadata(null));

しかし、プログラムを実行すると、このエラーが発生します

A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
Additional information: 'Func`2' type does not have a public TypeConverter class.  Error at Line 7 Position 122.

では、どのように TypeConverter を作成できますか? それは可能ですか?

編集

これが基本的に私のエンドゲームです。

私が撮影しているもの

4

1 に答える 1

1

あなたのクラス構造は私には本当にぎこちないようです。

UI は、外部ライブラリとのやり取りを配置するのに適した場所ではありません。

WPF を使用している場合は、The WPF Mentalityを採用する必要があります。

これは私がWPFでそれを行う方法です:

<UserControl x:Class="SiliconLabsRosettaStone.CP210UserControl"
             ...>
    <!-- ... Omitted for brevity -->

            <TextBlock Text="{Binding Caption}" ... />

            <TextBlock Text="{Binding NumberOfDevices}" />

            <Button Content="Execute" Click="Button_Click" ... />

    <!-- ... -->
</UserControl>

ユーザー制御コード ビハインド:

public class CP210UserControl: UserControl
{
   public CP210UserControl()
   {
       InitializeComponent();
   }

   private void Button_Click(object sender, RoutedEventArgs e)
   {
      var VM = DataContext as MyViewModel;
      if (VM != null)
      {
          //Correct uses of Code-Behind:

          //1 - Call ViewModel Methods:
          var response = VM.GetNumberDevices();

          //2 - UI-specific code which does not contain business logic:
          responseTextBlock.Background = response ? null : Brushes.Pink;
      }
   }
}

窓:

<Window ....>
   <local:CP210UserControl/>
</Window>

コードビハインド:

public class MainWindow: Window
{
    public MainWindow()
    {
       InitializeComponent();
       DataContext = new MyViewModel();
    }
}

ビューモデル:

public class MyViewModel: INotifyPropertyChanged
{
   public string Caption {get;set;} //NotifyPropertyChanged() required.

   public string NumberOfDevices {get;set;} //NotifyPropertyChanged() required.

   public bool GetNumberDevices()
   {
       int devices = 0;
       var result = CP210xWrapper.CP210x_GetNumDevices(ref devices);
       NumberOfDevices = string.Format("Number Of Devices:{0}", devices);

       return result == CP210x_STATUS.CP210x_SUCCESS;
   }

   //INotifyPropertyChanged implementation omitted for brevity.
}
  • 奇妙なFuncことは必要ありません。
  • 必要ありませんDependencyProperties
  • シンプルでシンプルなプロパティとINotifyPropertyChanged. これが、WPF でコーディングする方法です。
  • 実際のロジックと動作をコード ビハインドに入れる代わりに、ViewModel でメソッドを呼び出すためだけに、このようにコード ビハインドを使用することは完全に有効です。
  • WPF ロックス
  • さらにサポートが必要な場合はお知らせください。
于 2013-10-17T18:55:16.677 に答える