Доступ к свойствам пользовательского элемента управления в IValueConverter | silverlight 4

#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 элемента управления и вызвал этот метод из этих обратных вызовов.