Как я могу связать внутри этого ControlTemplate?
У меня есть ListView
, заполненный List<MyListItem>
и мне нужно использовать ControlTemplate
чтобы иметь возможность изменять эффекты при выборе элемента. Теперь у меня проблема в том, что {Binding MyProperty}
не работает внутри этого ControlTemplate
, Как я могу получить доступ к свойствам MyListItem
внутри шаблона?
Мой XAML выглядит так (упрощенно):
<ListView
Name="ListView"
Grid.Column="1"
IsSwipeEnabled="False">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="myColoredText" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Orange"/>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="myColoredText" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- Here I have my custom layout, removed for readability -->
<TextBlock
Name="myColoredText"
Foreground="Green"
Text="{Binding MyProperty}"/><!-- This does not work -->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Вот класс, стоящий за этим XAML:
public sealed partial class MyPage : Page
{
public MyPage()
{
InitializeComponent();
ListView.ItemsSource = new List<MyListItem>()
{
new MyListItem("Title1", "SubTitle1"),
new MyListItem("Title2", "SubTitle2")
}
}
}
и класс MyListItem:
class MyListItem
{
public string MyProperty { get; set; }
public string MyOtherProperty { get; set; }
public MyListItem(string myProperty, string myOtherProperty)
{
MyProperty = myProperty;
MyOtherProperty = myOtherProperty;
}
}
Самый маленький проект с проблемой:
4 ответа
В TextBox
, используйте:
Text="{Binding Content.MyProperty,
RelativeSource={RelativeSource TemplatedParent}}"
Wpf поддерживает привязку только к свойствам, а не к полям. Итак, ваш MyItemClass должен быть:
public class MyListItem {
public string MyProperty { get; set; }
public string MyOtherProperty { get; set; }
public MyListItem(string myProperty, string myOtherProperty) {
MyProperty = myProperty;
MyOtherProperty = myOtherProperty;
}
}
Надеюсь, поможет
Вам нужно использовать {TemplateBinding}
выражение при работе с обычаем ControlTemplate
s. Это связывает значения свойств с любыми соответствующими свойствами, связанными с экземпляром элемента управления.
<TextBlock Name="myColoredText"
Foreground="Green"
Text="{TemplateBinding MyProperty}" />
Это будет привязано непосредственно к указанному свойству экземпляра в вашем элементе управления. Так как элементы управления WPF/WinRT DependencyObjects
, DependencyProperties
обычно используются:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register(
"MyProperty",
typeof(Boolean),
typeof(ListViewItem),
null
);
public bool MyProperty
{
get { return (bool)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
Затем при объявлении нового экземпляра нужно заполнить это свойство, как это стандартно в XAML:
<someNamespace:ListViewItem MyProperty={Binding ViewModelProperty} />
Вы можете прочитать больше о выражении разметки TemplateBinding на MSDN.
ControlTemplate
обычно используется для определения того, как должен выглядеть элемент управления. Поэтому гораздо проще поместить свой XAML в DataTemplate
и назначить его ListView.ItemTemplate
собственность вместо Вы можете получить доступ ко всем вашим пользовательским свойствам из DataTemplate
:
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Name="myColoredText" Foreground="Green"
Text="{Binding MyProperty}" /><!-- This will now work -->
</DataTemplate>
</ListView.ItemTemplate>
ОБНОВЛЕНИЕ >>>
Вы также можете использовать DataTemplate
от ItemContainerStyle
свойство как это:
<Style x:Key="SomeStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate DataType="{x:Type Your:DataType}">
<TextBlock Name="myColoredText" Foreground="Green"
Text="{Binding MyProperty}" /><!-- This will now work -->
</DataTemplate>
</Setter.Value>
</Setter>
</Style>