Правильный способ создания настраиваемого Bindable WPF Control - PullRequest
0 голосов
/ 16 февраля 2020

Я хочу спросить о правильном пути, если я хочу создать Bindable пользовательский элемент управления, состоящий из двух элементов управления. Я не уверен в том, что я делаю - правильно ли я это делаю, потому что сталкиваюсь с некоторыми проблемами.

Вот что я пытаюсь сделать:

Позволяет называть этот элемент управления ucFlagControl. Создать новый пользовательский элемент управления ... Его цель - показать цветовую интерпретацию значения logi c (True / False) в переменной типа Bool.

Ранее я использовал Rectangle и привязывал FillProperty к bool ean-значению, используя Converter

. что я сделал usercontrol, и поместил прямоугольник и метку внутри, чем я добавил этот код:

 public partial class ucStatusFlag : UserControl
{
    public ucStatusFlag()
    {
        InitializeComponent();


    }

    public string LabelContent
    {
        get { return (string)GetValue(LabelContentProperty); }
        set
        {
            SetValue(LabelContentProperty, value);
            OnPropertyChanged("LabelContent");
        }
    }


    ///in case that I use integer or array
    public int BitIndex
    {
        get { return (int)GetValue(BitIndexProperty); }
        set
        {
            SetValue(BitIndexProperty, value);
            OnPropertyChanged("BitIndex");
        }
    }

    public string BindingSource
    {
        get { return (string)GetValue(BindingSourceProperty); }
        set
        {
            SetValue(BindingSourceProperty, value);
            OnPropertyChanged("BindingSource");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }


    /// <summary>
    /// Identified the Label dependency property
    /// </summary>
    public static readonly DependencyProperty LabelContentProperty =
        DependencyProperty.Register("LabelContent", typeof(string), typeof(ucStatusFlag), new PropertyMetadata("LabelContent"));

    public static readonly DependencyProperty BitIndexProperty =
        DependencyProperty.Register("BitIndex", typeof(int), typeof(ucStatusFlag), new PropertyMetadata(0));

    public static readonly DependencyProperty BindingSourceProperty =
        DependencyProperty.Register("(BindingSource", typeof(string), typeof(ucStatusFlag), new PropertyMetadata(""));


    private void StatusFlag_Loaded(object sender, RoutedEventArgs e)
    {
        if (BindingSource.Length > 0)
        {
            Binding bind = new Binding();
            string s = LabelContent;
            int i = BitIndex;


             bind.Converter = new StatusToColor();





            bind.Path = new PropertyPath(BindingSource);
            bind.ConverterParameter = BitIndex.ToString();
            bind.Mode = BindingMode.OneWay;
            bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            recStatusBit.SetBinding(Rectangle.FillProperty, bind);
        }
    }

    private class StatusToColor : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {

            byte bDataWordIdx;
            byte bDataBitIdx;

            Byte.TryParse((string)parameter, out bDataBitIdx);

            if (Object.ReferenceEquals(typeof(UInt16[]), value.GetType()))
            {
                UInt16[] uiaData = (UInt16[])value;
                bDataWordIdx = (byte)uiaData[0];


                if ((uiaData[bDataBitIdx / 16] >> (bDataBitIdx % 16) & 0x1) == 1)
                {
                    return Brushes.Green;
                }
                else
                {
                    return Brushes.Red;
                }
            }
            else if (Object.ReferenceEquals(typeof(UInt16), value.GetType()))
            {
                UInt16 uiaData = (UInt16)value;

                if (((uiaData >> bDataBitIdx) & 0x1) == 1)
                {
                    return Brushes.Green;
                }
                else
                {
                    return Brushes.Red;
                }
            }
            return 0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return 0;
        }
    }

}

} Чем я понял, что могу легко связывать контент, и мне не нужно создавать public static readonly DependencyProperty LabelContentProperty

но только свойство

 public new string Content
    {
        get { return (string)label.Content; }
        set
        {
            SetValue(label.Content, value);
            OnPropertyChanged("Content");
        }
    }

это переопределяет исходный контент, поэтому я могу связывать и / или назначать текст метки на верхнем уровне - например, в MainWindow.xaml, где размещен этот пользовательский элемент управления

Первый вопрос : если это в этом случае нормально, или если есть какой-то фон, о котором я не знаю, и я должен даже такие маленькие элементы управления делать по-другому - я хотел бы сделать длл. из него загрузить его на панель инструментов - я проверил это работает. И чем использовать его, например, в панели стека.

Второй вопрос заключается в том, что у меня есть проблема со свойством Fill" прямоугольника. Я не могу связать это свойство, как я связываю содержимое. Я знаю, что прямоугольник получен из Shape класс, так что я не уверен, имеет ли это какое-то отношение к этому.

Если я могу сделать внутреннее связывание или соединение так же, как в

Content

, я могу удалить преобразователи, чем и просто свяжите его, например, с файлом MainWindow.xaml (используя параметр converter и converter)

Но FillProperty у меня не работает, поэтому я не уверен в своей точке зрения.

Спасибо за предложения

РЕДАКТИРОВАТЬ:

хорошо, я извиняюсь, но я не уловил все, что вы хотите сказать в комментарии ниже. Не могли бы вы объяснить подробнее? I знаю, что приведенный выше код не является правильным способом сделать это ...? Или вы можете опубликовать любую статью об этом? Мой настоящий код выглядит так: В пользовательском элементе управления ... Я удалил весь код из кода позади .. .

'  <Label x:Name="lStatusBit"  Grid.Column="1" Padding="0" VerticalContentAlignment="Center" Margin="2,1,17,2"  />
        <Rectangle x:Name="recStatusBit"  Margin="0,3,1,7" />'

Свойство содержимого wo rks, я не вижу Rectangle и свойство заливки прямоугольника ... Другая проблема заключается в том, что если я заполню свойство Content в XAML, где размещен мой u c, Rectangle исчезнет.

1 Ответ

0 голосов
/ 19 февраля 2020

Наконец я нашел эту работу:

XAML

<UserControl x:Class="ucStatusFlag"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="17" d:DesignWidth="100" 
         x:Name="StatusFlag">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Rectangle x:Name="recStatusBit" Grid.Column="0" Stroke="Black" Width="11"  Fill="{Binding ElementName=StatusFlag, Path=RectangleColor}" Margin="0,2,0.2,3.8"  />
    <Label  Height="17" x:Name="lStatusBit" Foreground="Black" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" Margin="5,0,0,1" Content="{Binding ElementName=StatusFlag, Path=LabelContent}" />
</Grid>

C#

 public partial class ucStatusFlag : UserControl
{
    public ucStatusFlag()
    {
        InitializeComponent();


    }

    public string LabelContent
    {
        get { return (string)GetValue(LabelContentProperty); }
        set
        {
            SetValue(LabelContentProperty, value);

        }
    }



    public SolidColorBrush RectangleColor
    {
        get { return (SolidColorBrush)GetValue(RectangleColorProperty); }
        set
        {
            SetValue(RectangleColorProperty, value);

        }
    }

    public static readonly DependencyProperty RectangleColorProperty =
        DependencyProperty.Register("RectangleColor", typeof(SolidColorBrush), typeof(ucStatusFlag), new PropertyMetadata(Brushes.Gold));



    public static readonly DependencyProperty LabelContentProperty =
         DependencyProperty.Register("LabelContent", typeof(string), typeof(ucStatusFlag), new PropertyMetadata("LabelContent"));

}

Связывание в другом проекте:

   <ucStatusFlag HorizontalAlignment="Left" Height="18" Margin="154,224,0,0" VerticalAlignment="Top" Width="100" LabelContent="ABC" RectangleColor="{Binding RectangleColorPropertyInProject}"/>

Где RectangleColorPropertyInProject - свойство В определенной модели представления проекта

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...