加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 23:34:47 所属栏目:百科 来源:网络整理
导读:我正在处理一个显然简单的问题,即使用 WPF和MVVM显示油箱中的液位. 为了显示坦克,我使用了一个带有矩形的DockPanel.矩形的高度根据罐中的液体量而变化.在坦克的顶部,我有一个TextBlock,显示坦克中存在的液体量. 我在XAML中定义了这个: DockPanel x:Name="ta
我正在处理一个显然简单的问题,即使用 WPF和MVVM显示油箱中的液位.

为了显示坦克,我使用了一个带有矩形的DockPanel.矩形的高度根据罐中的液体量而变化.在坦克的顶部,我有一个TextBlock,显示坦克中存在的液体量.
我在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,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中的液体数量很简单,数据绑定可以完美地完成工作.但是,当涉及到矩形的高度时,会出现一些问题,因为我无法找到正确分离View和ViewModel之间关注点的方法.

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

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));
        }
    }
}

但是,我不能将此属性直接绑定到矩形的高度,并为这样的属性赋值,听起来像View应该负责的东西.
为了实现这一点,我必须在视图中插入一些代码,将这个百分比值转换为矩形的高度.

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

您对如何简化我已经实施的架构有任何建议吗?

解决方法

补充罗里.当您不需要固定的Converter参数但使用某个容器的实际高度时,也可以使用MultiBinding和IMultiValueConverter.

这允许使用父母的实际高度来设定液体的高度.

在我的例子中,我使用带边框的网格来代表gui上的液体罐.

视图模型:

public class MainWindowViewModel : PropertyChangedBase // from Calburn.Micro (see nuget)
{
    private int _liquidPerc;

    public MainWindowViewModel()
    {
        LiquidPercentage = 25;
    }

    public int LiquidPercentage
    {
        get { return _liquidPerc; }
        set
        {
            if (value == _liquidPerc) return;
            _liquidPerc= value;
            NotifyOfPropertyChange(() => LiquidPercentage);
        }
    }
}

转换器:

/// <summary>
/// Converter which expects two params. percentage and maximum height
/// </summary>
public class LiquidLevelConverter : IMultiValueConverter
{
    public object Convert(object[] values,Type targetType,object parameter,CultureInfo culture)
    {
        var percentage = (int) values[0];
        var maxHeight = (double) values[1];
        return percentage*maxHeight*0.01;
    }

    public object[] ConvertBack(object value,Type[] targetTypes,CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML:

<Window x:Class="UiLiquedTankDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:UiLiquedTankDemo"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:MainWindowViewModel x:Key="ViewModel" />
        <local:LiquidLevelConverter x:Key="LiquidLevelConverter" />
    </Window.Resources>
    <DockPanel DataContext="{StaticResource ViewModel}">

        <!-- move the slider to move the level of the liquid --> 
        <Slider Minimum="0" Maximum="100" Value="{Binding LiquidPercentage}" 
                DockPanel.Dock="Bottom" 
                Margin="0"/>

        <!-- Liquid container representation using a grid --> 
        <Grid Name="LiquidContainer" Margin="200,5">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <Border Grid.Row="1" Background="Blue" Margin="0">
                <Border.Height>
                    <MultiBinding Converter="{StaticResource LiquidLevelConverter}">
                        <Binding Path="LiquidPercentage"></Binding>
                        <Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type Grid}}"></Binding>
                    </MultiBinding>
                </Border.Height>
            </Border>

            <Border Grid.Row="0" Grid.RowSpan="2"  BorderBrush="Black" BorderThickness="1" />
        </Grid>

    </DockPanel>
</Window>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读