#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); ... }