WPF数据绑定计算值有时几分钟有时几个小时
-
21-08-2019 - |
题
我有一个带有文本框的 WPF 窗口,使用标准 WPF 数据绑定到对象。这一切都很好,问题是这样的:
用户正在输入时间估计,我想为用户提供以小时或分钟为单位输入数据的选项(通过下拉列表)。我想将数据保存在几分钟内,如果用户选择小时,请将其输入乘以 60 并存储数据。
如何使用 WPF 数据绑定实现这一目标?这可能吗?
编辑
例如,如果下拉列表设置为小时,则 90 分钟将显示为 1.5,但如果选择分钟,则显示为 90。
解决方案
您可以在你的窗户上使用一个特殊的属性:
<ComboBox x:Name="Units">
<sys:String>Hours</sys:String>
<sys:String>Minutes</sys:String>
</ComboBox>
<TextBox x:Name="Value" Text="{Binding Path=Estimate, ElementName=ThisWindow}" />
和然后实现特殊属性:
public double Estimate
{
get
{
switch(this.Units.SelectedItem as String)
{
case "Hours":
return this.estimate / 60.0;
default:
return this.estimate;
}
}
set
{
switch(this.Units.SelectedItem as String)
{
case "Hours":
this.estimate = value * 60.0;
break;
default:
this.estimate = value;
break;
}
this.OnPropertyChanged("Estimate");
}
}
其他提示
在第一个完全误解的问题,这是我努力的让我的第一奖金;)
<Window.Resources>
<local:DivisionConverter x:Key="HoursConverter" Divisor="60"/>
<DataTemplate DataType="{x:Type local:MyObject}">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="InputBox" Text="{Binding Path=Estimate}" Width="80"/>
<ComboBox x:Name="InputUnit" SelectedItem="Minutes">
<System:String>Minutes</System:String>
<System:String>Hours</System:String>
</ComboBox>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding ElementName=InputUnit, Path=SelectedItem}" Value="Hours">
<Setter TargetName="InputBox" Property="Text" Value="{Binding Path=Estimate, Converter={StaticResource HoursConverter}}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl VerticalAlignment="Top">
<local:MyObject Estimate="120"/>
</ContentControl>
</Grid>
在一般我不喜欢的专业转换器:一段时间后,你失去跟踪哪个转换器做究竟是什么,以及你最终通过转换器的代码会每次你认为你需要一个,或者更糟你建立的第二个它不完全一样。所以,现在我只使用他们,当一切都失败了。
相反,我定义一个通用的 DivisionConverter 的,这将在所述的转换方法的价值,乘以在ConvertBack方法的价值,正如您所料,没必要看代码这里;)
Additionaly我使用一个DataTemplate和触发器在别人使用MultiBinding或(IMO更糟)在吸气和setter加入此UI逻辑。这使所有的这种相对简单的UI逻辑在一个overseeable地方。
现在只是要完成这是后台代码:
public class MyObject
{
public double Estimate { get; set; }
}
public class DivisionConverter : IValueConverter
{
public double Divisor { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double doubleValue = (double)value;
return doubleValue / Divisor;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
double inputValue;
if (!double.TryParse((string)value, NumberStyles.Any, culture, out inputValue))
return 0;
return inputValue * Divisor;
}
}
可以使用一个MultiValueConverter:
<强> XAML 强>
<ComboBox ItemsSource="{StaticResource values}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource minutToHours}">
<Binding/>
<Binding Path="IsChecked" ElementName="chkHours"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<CheckBox Name="chkHours" Content="Show hours"/>
转炉的 C#代码强>
public class MinuteToHoursConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int minutes = 0;
if (values[0] is TimeSpan)
{
minutes = (int)((TimeSpan)values[0]).TotalMinutes;
}
else
{
minutes = System.Convert.ToInt32(values[0]);
}
bool showHours = System.Convert.ToBoolean(values[1]);
if (showHours)
return (minutes / 60.0).ToString();
else
return minutes.ToString();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
#endregion
}
但这种方法可能不是最优的......恕我直言,最好的办法,如果你使用MVVM模式是创建视图模型额外的属性来计算正确的值
也许我该得太多,但由于组合框既具有显示值和实际值(幕后的从用户),为什么不把你的估计列表有两列......两个小时并分别分钟。然后,根据取模式被选中时,只是改变了“显示”结合于相应的一个。通过这种方式,它会永远保存你想要的背后的幕后分钟数。从没有其他转换到/