单独绑定到模板化控件的多个实例
本文关键字:实例 模板化控件 绑定 单独 | 更新日期: 2023-09-27 18:05:40
我希望使用模板和MVVM模式创建类似控件的网格。下面是对我遇到的问题的简单描述。我首先为网格的每个元素定义一个类Element:
public class Element : INotifyPropertyChanged
{
private string _dText = "Default";
public string dText { get { return _dText; } set { _dText = value; NotifyPropertyChanged("dText"); } }
internal Element(string aText) { dText = aText; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(info));
}
}
然后我在ViewModel类中实例化一些元素,该类是页面的DataContext,如下所示:
public class MinVM
{
private Element _element0 = new Element("Element0 initialization text 0");
public Element element0 { get { return _element0; } set { _element0 = value; } }
private Element _element1 = new Element("Element1 initialization text 1");
public Element element1 { get { return _element1; } set { _element1 = value; } }
}
现在,在XAML页面。我创建了一个ControlTemplate,目的是让我得到一些很好的居中文本,如下所示:
<ControlTemplate x:Name="cTemplate" x:Key="CTemplate" TargetType="ContentControl">
<Grid x:Name="ctGrid" Background="Orange" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBox x:Name ="dtBox" Background="Orange" BorderThickness="0"
VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"
Text="{Binding dText, FallbackValue=Default control template text}">
</TextBox>
</Grid>
</ControlTemplate>
最后,在Page内容本身,我实例化网格和其中的元素,如下所示:
<ContentControl x:Name="element0" Grid.Row="0" Template="{StaticResource CTemplate}" Content="{Binding Path=element0}"></ContentControl>
<ContentControl x:Name="element1" Grid.Row="1" Template="{StaticResource CTemplate}" Content="{Binding Path=element1}"></ContentControl>
这一切都呈现得很好,正如你所期望的,但是绑定不起作用,也就是说,我不能改变默认文本,因为WPF正在MinVM中寻找字段dText,而不是在元素中。这是因为ControlTemplate忽略了Content="{Binding Path=element0}"
尝试和修复它的明显方法是使用DataTemplate而不是ControlTemplate。我已经这样做了-创建了一个DataTemplate与上面的ControlTemplate完全相同的内部,Key="DTemplate"。然后将实例化XAML更改为
<ContentControl x:Name="element0" Grid.Row="0" ContentTemplate="{StaticResource DTemplate}" Content="{Binding Path=element0}"></ContentControl>
<ContentControl x:Name="element1" Grid.Row="1" ContentTemplate="{StaticResource DTemplate}" Content="{Binding Path=element1}"></ContentControl>
现在绑定工作正常,正如您所期望的那样—我可以愉快地更改控件文本。但是渲染不再正常工作(文本不再在Grid元素中居中,并且橙色不再填充Grid单元格),因为我已经丢失了ControlTemplate
所以,我可以让它正确渲染,或者绑定,但不能两者都要
如果我正确理解你需要什么,那么下面的XAML适合我(你可以提取样式):
<Window x:Class="WpfScratch.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:WpfScratch"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="ContentTemplate">
<TextBox TextAlignment="Center" Text="The obvious way to try and fix it is to use a DataTemplate instead of a ControlTemplate. I've done that - created a DataTemplate with exactly the same internals as the above ControlTemplate, with Key=DTemplate. I then change the instantiation XAML to" TextWrapping="Wrap"/>
</DataTemplate>
<Style x:Key="ContentControlStyle1" TargetType="{x:Type ContentControl}">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="ContentTemplate" Value="{StaticResource ContentTemplate}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ContentControl Margin="4" Style="{DynamicResource ContentControlStyle1}"/>
</Grid>
</Window>