我正在开发一个使用Silicon Labs SDK的项目。在为SDK创建包装器之后,我创建了一个WPF项目来可视化SDK中的一些结果。我的第一个测试是使用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?它甚至可能吗?
修改
这基本上是我最终的游戏。
答案 0 :(得分: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中编码的方式。