C#和#x2B;WPF:访问控件值时,我应该如何进行适当的检查/保护/强制转换?
这可能是非常基本的,但在与其他语言合作多年后,我刚刚开始学习C语言,不幸的是,我已经习惯了松散和动态的键入。现在,在构建一个带有很多复选框的WPF表单时,我注意到,由于需要检查空值并强制转换结果,我的代码用于做一些简单的事情,比如确定是否选中复选框,实际上相当复杂。我最终得到的帮助函数如下:C#和#x2B;WPF:访问控件值时,我应该如何进行适当的检查/保护/强制转换?,c#,.net,wpf,casting,C#,.net,Wpf,Casting,这可能是非常基本的,但在与其他语言合作多年后,我刚刚开始学习C语言,不幸的是,我已经习惯了松散和动态的键入。现在,在构建一个带有很多复选框的WPF表单时,我注意到,由于需要检查空值并强制转换结果,我的代码用于做一些简单的事情,比如确定是否选中复选框,实际上相当复杂。我最终得到的帮助函数如下: private bool isChecked(CheckBox control) { return control != null && control.IsChec
private bool isChecked(CheckBox control) {
return control != null && control.IsChecked != null && control.IsChecked.HasValue && (bool)control.IsChecked;
}
所以在我的逻辑代码中,我可以
if (isChecked(opticsCheckBox))
{
// whatever I need to do if opticsCheckBox is checked
}
这是用C#(使用WPF)做事情的正常方式,还是我遗漏了一些简单的东西?基本上,我发现嵌套的条件层总是检查每个对象是否为null,这是错误代码的警告标志(事实上,我可能会忘记检查)。但我不确定我应该做什么
我应该使用try。。。即使控件不存在或未检查也不是一种例外情况,也要到处捕获?在我看来,它最终也会变得杂乱无章
另一个澄清的例子是:
当我想写一些像:
maxWeight = (int)maxWeightComboBox.SelectedItem;
我发现自己在写:
if (maxWeightComboBox != null && maxWeightComboBox.SelectedItem != null)
{
ComboBoxItem item = (ComboBoxItem)maxWeightComboBox.SelectedItem;
maxWeight = Int32.Parse(item.Content.ToString());
}
一般来说,是的,C#比动态/丢失类型的语言更冗长。Java也是如此。看看你的具体例子
private bool isChecked(CheckBox control) {
return control != null && control.IsChecked != null && control.IsChecked.HasValue && (bool)control.IsChecked;
}
有几点。。。以下两项检查是等效的:
control.IsChecked != null
control.IsChecked.HasValue
IsChecked属性是可为空的类型。由于您是C#新手,我建议您阅读价值类型与参考类型。一旦掌握了其中的诀窍,就可以了解如何使用可空类型包装值类型,以便为其分配空值。下面链接的页面解释了上述twp声明等效的原因:
control.IsChecked != null
control.IsChecked.HasValue
第二,你为什么要检查控制=无效的在典型的场景中,在窗口或UserControl上用XAML创建控件,通过x:Name属性进行标识。在这种情况下,您可以依赖UI中存在的控件并放弃此检查
您的另外两张支票是必需的;-)
把它们放在一个可以重复使用的方法中是个好主意。您还可以通过创建扩展方法来“扩展”语言,例如
private bool IsChecked(this CheckBox control) {
return control.IsChecked.HasValue && (bool)control.IsChecked;
}
// calls the extension method above.
myCheckBox.IsChecked()
这很有帮助。一般来说,是的,C#比动态/丢失类型的语言更冗长。Java也是如此。看看你的具体例子
private bool isChecked(CheckBox control) {
return control != null && control.IsChecked != null && control.IsChecked.HasValue && (bool)control.IsChecked;
}
有几点。。。以下两项检查是等效的:
control.IsChecked != null
control.IsChecked.HasValue
IsChecked属性是可为空的类型。由于您是C#新手,我建议您阅读价值类型与参考类型。一旦掌握了其中的诀窍,就可以了解如何使用可空类型包装值类型,以便为其分配空值。下面链接的页面解释了上述twp声明等效的原因:
control.IsChecked != null
control.IsChecked.HasValue
第二,你为什么要检查控制=无效的在典型的场景中,在窗口或UserControl上用XAML创建控件,通过x:Name属性进行标识。在这种情况下,您可以依赖UI中存在的控件并放弃此检查
您的另外两张支票是必需的;-)
把它们放在一个可以重复使用的方法中是个好主意。您还可以通过创建扩展方法来“扩展”语言,例如
private bool IsChecked(this CheckBox control) {
return control.IsChecked.HasValue && (bool)control.IsChecked;
}
// calls the extension method above.
myCheckBox.IsChecked()
这很有帮助。不太详细的表单是
control != null && control.IsChecked == true
请记住,bool?
有三个值,true、false和null,只需检查一个值即可。例如,a==true
和a!=false
分别是检查空值何时像false一样工作或空值何时像true一样工作
对于您的组合框示例,我首先使用强类型集合。有关如何直接绑定到整数的示例,请参见(或者如果需要单独的内容/值,请将其绑定到KeyValuePairs列表[例如]),然后使用SelectedValue和SelectedValuePath来减少值检索代码。不太详细的表单是
control != null && control.IsChecked == true
请记住,bool?
有三个值,true、false和null,只需检查一个值即可。例如,a==true
和a!=false
分别是检查空值何时像false一样工作或空值何时像true一样工作
对于您的组合框示例,我首先使用强类型集合。有关如何直接绑定到整数的示例,请参见(或者如果需要单独的内容/值,请将其绑定到KeyValuePairs列表[例如]),然后使用SelectedValue和SelectedValuePath减少值检索代码。使用可空类型(包括引用),您可以使用
?
运算符指定对象为空时要使用的默认值。所以control.IsChecked!=null&&control.IsChecked
可以替换为control.IsChecked??错误
。这并不能解决所有问题,但在某些情况下,它有助于减少您键入的代码量。对于可为空的类型(包括引用),您可以使用?
运算符指定对象为空时要使用的默认值。所以control.IsChecked!=null&&control.IsChecked
可以替换为control.IsChecked??错误
。这并不能解决所有问题,但在某些情况下,它有助于减少键入的代码量。WPF提供了属性更改通知、依赖属性和绑定等功能。
因此,WPF中的良好实践是使用PresentationModelView模式或MVC模式,而不是直接访问控件
您的表示模型(或控制器)必须处理所有业务逻辑,视图只反映模型的实际状态
在您的案例中,模型如下所示:
public class SampleModel : ObservableObject
{
private bool? _isFirstChecked;
public bool? IsFirstChecked
{
get
{
return this._isFirstChecked;
}
set
{
if (this._isFirstChecked != value)
{
this._isFirstChecked = value;
this.OnPropertyChanged("IsFirstChecked");
}
}
}
private int _maxWeight;
public int MaxWeight
{
get
{
return this._maxWeight;
}
set
{
if (this._maxWeight != value)
{
this._maxWeight = value;
this.OnPropertyChanged("MaxWeight");
}
}
}
public IEnumerable<int> ComboBoxItems
{
get
{
yield return 123;
yield return 567;
yield return 999;
yield return 567;
yield return 1999;
yield return 5767;
yield return 9990;
}
}
}
因此,现在我们有了一个带有必要属性声明的表示模型,让我们看看视图:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self ="clr-namespace:Test"
Title="MainWindow"
Height="350" Width="525">
<Window.Resources>
<self:NullableBoolToStringConvreter x:Key="nullableBoolToStringConverter" />
</Window.Resources>
<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center">IsFirstChecked:</Label>
<CheckBox VerticalAlignment="Center"
IsChecked="{Binding Path=IsFirstChecked}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center">Max Weight:</Label>
<ComboBox ItemsSource="{Binding Path=ComboBoxItems}"
VerticalAlignment="Center"
SelectedValue="{Binding Path=MaxWeight}">
</ComboBox>
</StackPanel>
<TextBox Text="{Binding Path=MaxWeight}" />
<TextBox Text="{Binding Path=IsFirstChecked, Converter={StaticResource nullableBoolToStringConverter}}"/>
<Button Click="Button_Click" Content="Reset combo box to 999 and checkbox to null"/>
</StackPanel>
</Grid>
如您所见,我们在MainWindow构造函数中创建SampleModel实例,设置其属性并设置
<CheckBox IsThreeState="false" IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
public bool IsChecked { get; set; }
<ComboBox ItemsSource="{Binding Numbers}" SelectedItem="{Binding SelectedNumber, Mode=TwoWay}"/>
public IEnumerable<int> Numbers { get { return new[] { 1, 2, 3, 4, 5, 6 }; } }
public int? SelectedNumber { get; set; }
Console.WriteLine(SelectedNumber == null
? "No number was selected."
: SelectedNumber + " was selected.);