我有一个带有文本框的 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模式是创建视图模型额外的属性来计算正确的值

也许我该得太多,但由于组合框既具有显示值和实际值(幕后的从用户),为什么不把你的估计列表有两列......两个小时并分别分钟。然后,根据取模式被选中时,只是改变了“显示”结合于相应的一个。通过这种方式,它会永远保存你想要的背后的幕后分钟数。从没有其他转换到/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top