Присоединенная собственность WPF

#wpf #attached-properties

#wpf #прилагаемые-свойства

Вопрос:

Я создал простой тестовый проект, который создает список, заполненный флажками. У меня есть кодовое указание, что всякий раз, когда флажки установлены, в текстовом поле над списком отображается текст всех выбранных элементов. Все работает, но сейчас я пытаюсь создать Вложенное свойство (опять же в коде), которое позволяет включать префикс. В конце концов, я хочу преобразовать это в стандарты MVVM, но поскольку я относительно новичок в WPF и очень новичок в MVVM, мне нравится работать с рабочим образцом проекта и постепенно преобразовывать каждую часть в проект MVVM, поскольку я нахожу, что это помогает мне лучше понять, что происходит. Мой код приведен ниже:

xaml:

 lt;Window x:Class="CheckBoxList.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:CheckBoxList"  mc:Ignorable="d"  Title="MainWindow" Height="400" Width="400"gt; lt;Window.Resourcesgt;  lt;Style x:Key="CheckBoxListStyle" TargetType="{x:Type ListBox}"gt;  lt;Setter Property="SelectionMode" Value="Multiple"gt;lt;/Settergt;  lt;Setter Property="ItemContainerStyle"gt;  lt;Setter.Valuegt;  lt;Style TargetType="{x:Type ListBoxItem}" gt;  lt;Setter Property="Margin" Value="2" /gt;  lt;Setter Property="Template"gt;  lt;Setter.Valuegt;  lt;ControlTemplate TargetType="{x:Type ListBoxItem}"gt;  lt;CheckBox  IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"  Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"gt;  lt;ContentPresentergt;lt;/ContentPresentergt;  lt;/CheckBoxgt;  lt;/ControlTemplategt;  lt;/Setter.Valuegt;  lt;/Settergt;  lt;/Stylegt;  lt;/Setter.Valuegt;  lt;/Settergt;  lt;/Stylegt; lt;/Window.Resourcesgt; lt;Grid Margin="8"gt;  lt;Grid.RowDefinitionsgt;  lt;RowDefinition Height="30"/gt;  lt;RowDefinition/gt;  lt;RowDefinition Height="Auto"gt;lt;/RowDefinitiongt;  lt;RowDefinition Height="30"/gt;  lt;/Grid.RowDefinitionsgt;  lt;TextBox Grid.Row="0" x:Name="ListBoxTextBox"/gt;  lt;ListBox Grid.Row="1" Style="{StaticResource CheckBoxListStyle}" Name="lstProducts" local:MainWindow.PrefixMark="gt;"  DisplayMemberPath="ModelName"gt;  lt;/ListBoxgt;  lt;Button Grid.Row="2" Margin="0,5,0,0" Click="cmdGetSelectedItems"gt;Get Selected Itemslt;/Buttongt;  lt;CheckBox Grid.Row="3" Content="Test" Margin="5"/gt; lt;/Gridgt;  

xaml.cs

 public static string GetPrefixMark(DependencyObject obj)  {  string t = (string)obj.GetValue(PrefixMarkProperty);  return (string)obj.GetValue(PrefixMarkProperty);  }   public static void SetPrefixMark(DependencyObject obj, string value)  {  obj.SetValue(PrefixMarkProperty, value);  string t = (string)obj.GetValue(PrefixMarkProperty);  }   // Using a DependencyProperty as the backing store for PrefixMark. This enables animation, styling, binding, etc...  public static readonly DependencyProperty PrefixMarkProperty =  DependencyProperty.RegisterAttached("SetPrefixMark", typeof(string), typeof(MainWindow), new PropertyMetadata("('"));  private void CheckBox_Checked(object sender, RoutedEventArgs e)  {  if (sender is FrameworkElement element)  {  AddText(element);  }  } private void AddText(FrameworkElement e)  {  StringBuilder sB = new StringBuilder("");  foreach (Product product in lstProducts.SelectedItems)  {  sB.Append(product.ModelName).Append(ValueSeparator);  }  if (sB.Length gt; 0)  {  sB.Remove(sB.Length - (ValueSeparator).Length, (ValueSeparator).Length);  }  if (sB.Length gt; 0)  {   ListBoxTextBox.Text = GetPrefixMark(e)   sB.ToString();  }  else  {  ListBoxTextBox.Text = "";  }  }  

Когда я запускаю программу, хотя префиксная метка установлена при загрузке, когда я устанавливаю флажок, она возвращается к значению по умолчанию. Я могу только предположить, что это создается дважды, но ни за что на свете я не могу понять, почему и как решить эту проблему?

Комментарии:

1. RegisterAttached("SetPrefixMark", ...) должно быть RegisterAttached("PrefixMark", ...) . Кроме того, какова цель string t методов get и set свойства?

2. @Клеменс. Спасибо вам за оперативный ответ. Строка t осталась от меня, когда я пытался определить проблему. К сожалению, предложенное вами решение не работает. Метка setprefix больше не запускается при запуске, и при установке флажка метка префикса по-прежнему возвращает значение по умолчанию?

3. Это не было задумано как «решение», скорее как необходимое условие. Когда вы пишете local:MainWindow.PrefixMark=... в XAML, свойство должно быть зарегистрировано под именем PrefixMark , и больше ничего. Однако я не могу найти в вашем коде место, где это свойство действительно используется.

4. Я не понимаю, почему префикс должен быть объявлен в xaml. он используется в коде c#, объявляет строковую константу для префикса

5. или вы можете привязать текстовое поле. Текст и включите этот префикс в формат строки привязки

Ответ №1:

Для начала вы должны передать фактическое имя свойства зависимости Register методу:

 DependencyProperty.RegisterAttached("PrefixMark", ...  

Метка Setprefix больше не запускается при запуске

Этого не должно быть. Если вы хотите задать Text свойство TextBox при запуске, вам следует либо привязать его к свойству источника, либо задать его программно:

 public MainWindow() {  InitializeComponent();  ListBoxTextBox.Text = GetPrefixMark(this);  ... }