#silverlight #xaml #ivalueconverter
#silverlight #xaml #ivalueconverter
Вопрос:
Я пытаюсь написать пользовательский элемент управления silverlight, который представляет резервуар для воды. Он имеет два свойства зависимостей, liquidLevel и liquidCapacity, и я хочу передать оба этих параметра в конвертер вместе с GradientBrush. Идея заключается в том, что конвертер выполнит вычисления на основе уровня жидкости и емкости и отрегулирует остановки градиента на кисти, чтобы создать видимость подъема и падения жидкости.
в моем резервуаре есть «окно», которое представляет собой просто прямоугольник и градиентную кисть, пока у меня есть это
Мой шаблон элемента управления
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MoreControls;assembly=MoreControls"
xmlns:assets="clr-namespace:MoreControls.Assets">
<LinearGradientBrush x:Name="LiquidLevelTankWindow" StartPoint="0.469,0.997" EndPoint="0.487,0.013">
<GradientStop Color="#FF1010F1" Offset="0.0"/>
<GradientStop Color="#FF5555FB" Offset="0.55"/>
<GradientStop Color="#FFE4E4F1" Offset="0.6"/>
<GradientStop Color="#FFFAFAFD" Offset="1"/>
</LinearGradientBrush>
<assets:LiquidLevelBrushConverter x:Name="LiquidLevelBrushConverter" levelBrush="{StaticResource LiquidLevelTankWindow}"/>
<Style x:Key="Liquid" TargetType="local:LiquidTank">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:LiquidTank">
// * parts of the control here *
// the part of the control im interested in
<Rectangle x:Name="TankWindow" Width="32.3827" Height="64" Canvas.Left="27" Canvas.Top="42" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000310"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LiquidLevel, Converter={StaticResource LiquidLevelBrushConverter}}" />
// * rest of control template *
Использование элемента управления в xaml (в конечном итоге я хочу связать эти свойства)
<local:LiquidTank Style="{StaticResource Liquid}" LiquidCapacity="100" LiquidLevel="50"/>
и конвертер
public class LiquidLevelBrushConverter : IValueConverter
{
public LinearGradientBrush levelBrush { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//I can access the liquid level parameter here
double level = 0;
double.TryParse(value.ToString(), out level);
GradientStopCollection gsc = levelBrush.GradientStops;
//some logic to alter gradient stops
return null;
}
Сейчас я хочу получить доступ ко второму управляющему свойству liquidCapacity из моего конвертера, чтобы я мог рассчитать процент заполнения резервуара. Я попытался передать liquidCapacity в качестве параметра конвертера, но если это возможно, я не могу разобраться в синтаксисе (я довольно новичок в silverlight).
Теперь, когда я зашел так далеко, я думаю, что мог бы создать одно свойство dependancyproperty с именем fillpercentage и выполнить это вычисление в конечном viewmodel, но с учетом того, как данные будут организованы там, я уверен, что у меня возникнет целый ряд новых проблем, если я попробую это. Мне кажется более управляемым иметь возможность жестко запрограммировать liquidcapacity в xaml и привязать liquidlevel к viewmodel. Модель представления будет извлекать кучу значений из базы данных в наблюдаемый словарь, одним из которых является liquidlevel, поэтому, я думаю, было бы намного проще привязать liquidlevel непосредственно к наблюдаемому словарю, а не пытаться преобразовать его в «fillpercentage» в модели представления передпривязка его.
Кроме того, я довольно упрям, и в интересах моего образования кто-нибудь знает, возможно ли то, что я предложил сделать. Если да, то как правильно это сделать?
Ответ №1:
Когда вы говорите, что вы
пытались передать liquidCapacity в качестве параметра конвертера
Я подозреваю, что вы пытаетесь сделать что-то вроде
<Rectangle Fill="{Binding Path=LiquidLevel, ConverterParameter={Binding Path=LiquidCapacity} ...}" />
Это не сработает. Вы не можете иметь привязку внутри другой привязки.
Лично я бы не стал использовать конвертер для того, что вы пытаетесь сделать. Вместо этого я бы добавил метод для настройки остановок градиента LinearGradientBrush в код элемента LiquidTank
управления. Затем я бы добавил PropertyChangedCallback
s к свойствам LiquidLevel
и LiquidCapacity
зависимостям LiquidTank
элемента управления и вызвал этот метод из этих обратных вызовов.