【发布时间】:2016-09-05 17:56:06
【问题描述】:
我正在寻找使用模板和 MVVM 模式创建类似控件的网格。这是我遇到的问题的简单描述。 我首先为 Grid 的每个元素定义一个要实例化的类 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 类中实例化一些 Elements,它是 Page 的 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 Page.PageResources 中,我创建了一个 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>
最后,在页面内容本身中,我实例化了网格和其中的元素,如下所示:
<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 内而不是 Element 内寻找字段 dText。这是因为 ControlTemplate 忽略了 Content="{Binding Path=element0}"
尝试修复它的明显方法是使用 DataTemplate 而不是 ControlTemplate。我已经做到了 - 创建了一个与上述 ControlTemplate 具有完全相同的内部结构的 DataTemplate,其中 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
所以,我可以让它正确渲染,也可以绑定,但不能两者兼而有之。
【问题讨论】: