c# – 如何将ViewModel中的信息转换为在View中显示
我正在处理一个显然简单的问题,即使用
WPF和MVVM显示油箱中的液位.
为了显示坦克,我使用了一个带有矩形的DockPanel.矩形的高度根据罐中的液体量而变化.在坦克的顶部,我有一个TextBlock,显示坦克中存在的液体量. <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> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |