c# - 如何将 ViewModel 中的信息转换为显示在 View 中

标签 c# wpf mvvm

我正在处理一个看似简单的问题,即使用 WPF 和 MVVM 显示 jar 中的液位。

为了展示坦克,我使用了一个内部有一个矩形的 DockPanel。矩形的高度根据 jar 中的液体量而变化。在水箱顶部,我有一个 TextBlock,它显示 Tank 中存在的液体量。 我在 XAML 中这样定义它:

<DockPanel x:Name="tankView" HorizontalAlignment="Left" Height="212" VerticalAlignment="Top" Width="144" DataContext="{Binding Source={StaticResource TankViewModel}}">
            <TextBlock x:Name="oilQuantity" HorizontalAlignment="Right" VerticalAlignment="Top" DockPanel.Dock="Top" Margin="0,0,10,0" Text = "{Binding TxtOilQuantity, Mode=OneWay}"/>
            <Rectangle x:Name="oilLevel" Fill="Green" Height="66" Stroke="Black" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" DockPanel.Dock="Bottom"/>
</DockPanel>

您还可以看到,我已经按照 MVVM 模式创建了一个 TankViewModel 类和一个 TankModel 类。

在 TextBlock 中显示液体的数量很简单,数据绑定(bind)可以完美地完成这项工作。但是,当涉及到矩形的高度时,会出现一些问题,因为我无法找到一种方法来正确分离 View 和 View 模型之间的关注点。

矩形的高度取决于最大容量和水箱中的液体量,这样我可以获得一个数字,告诉我水箱的填充百分比,如下所示:

public class TankViewModel : INotifyPropertyChanged
{
    private TankModel tankModel = new TankModel(2500);

    public int IntFilledPercentage {
        get {
            if (tankModel.OilQuantity == 0)
                return 0;
            else
                return Convert.ToInt32(((double)tankModel.OilQuantity / tankModel.capacity) * 100);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(String info) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

但是,我无法将此属性直接绑定(bind)到矩形的高度,并且为此类属性赋值听起来像是 View 应该负责的事情。 为此,我必须在 View 中插入一些代码,将此百分比值转换为矩形的高度。

我可以通过实现 View 的 OnPropertyChanged() 回调来实现吗?

对于如何简化我已建立的架构,您有什么建议吗?

最佳答案

您可以使用 View 模型中的百分比值通过一些数学运算轻松完成此操作。您知道 View 中矩形的最大高度(它可能是一个静态值)。那么当前高度=最大高度乘以百分比值。

可以使用 the Binding.Converter property with an IValueConverter 在 XAML 中执行此类操作.参见 this post , 这是相关的。

这是一个示例转换器:

internal sealed class OilLevelConverter : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var percentage = (decimal) value;
        var maxLevel = System.Convert.ToInt32((string) parameter);
        var currentLevel = System.Convert.ToInt32(maxLevel * percentage);
        return currentLevel;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

这是您的 App.xaml:

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <local:ViewModel x:Key="ViewModel" />
        <local:OilLevelConverter x:Key="OilLevelConverter"/>
    </Application.Resources>
</Application>

这是一个示例窗口 XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" 
        Width="525" 
        DataContext="{StaticResource ViewModel}" >

    <Grid>
        <Rectangle Fill="#FFF4F4F5" 
                   HorizontalAlignment="Left" 
                   Height="{Binding Path=OilLevel, 
                    Converter={StaticResource OilLevelConverter}, 
                    ConverterParameter=100}" Margin="183,132,0,0" 
                    Stroke="Black" VerticalAlignment="Top" Width="100"/>
    </Grid>
</Window>

注意:我省略了只有一个属性的 ViewModel:OilLevel

关于c# - 如何将 ViewModel 中的信息转换为显示在 View 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39040255/

相关文章:

c# - 为什么 new FontFamily ("Invalid font") 不抛出异常?

c# - 使用 MVVM 的 WPF 脚手架?

wpf - ViewModel 中的 RoutedUICommand 与 ICommand 以及使用 InputBinding

WPF 如何始终在 TreeView 上显示扩展器

.net - 如何使用 MVVM 更改数据网格或 ListView 中的内容

wpf - 如何在 WPF 中更改 DynamicResource

c# - 如何使用异步 Web 请求进行多线程处理

c# - 已发布的控制台应用程序上没有 .NET Core 2.0 应用程序设置

wpf - 如何正确实现 INotifyDataErrorInfo?

c# - MVVMCross:在 android xml 中绑定(bind)嵌套属性