如何使用在Application.Resources中定义的DataTemplate?

3

如果我的Windows无法访问Application.Resources中定义的资源,那么Application.Resources的目的是什么?

这样做是有效的,我可以得到一个带有文本框的窗口,里面写着“Loki”...

App.xaml.cs:

public partial class App : Application
{
  protected override void OnStartup(StartupEventArgs e)
  {
    base.OnStartup(e);

    ViewModel.ViewModel1 oVM = new ViewModel.ViewModel1 { Name = "Loki" };
    MainWindow oVW = new MainWindow { Content = oVM };

    oVW.ShowDialog();
  }
}

MainWindow.xaml

<Window x:Class="TableGenerator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:TableGenerator.ViewModel"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <DataTemplate DataType="{x:Type vm:ViewModel1}">
      <TextBox Text="{Binding Path=Name}" />
    </DataTemplate>
  </Window.Resources>
  <ContentPresenter />
</Window>

将DataTemplate从Window.Resources移动到Application.Resources并不起作用。当我运行这个程序时,窗口中没有文本框,但是有一些文本被显示出来,只是显示了我的视图模型类的名称,“TableGenerator.ViewModel.ViewModel1”。

App.xaml.cs没有改变。

MainWindow.xaml更改为:

<Window x:Class="TableGenerator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <ContentPresenter />
</Window>

App.xaml:

<Application x:Class="TableGenerator.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="clr-namespace:TableGenerator.ViewModel">
  <Application.Resources>
    <DataTemplate DataType="{x:Type vm:ViewModel1}">
      <TextBox Text="{Binding Path=Name}" />
    </DataTemplate>      
  </Application.Resources>
</Application>

为什么它不会在Application.Resources中查找我的DataTemplate?

你尝试使用ContentControl而不是ContentPresenter了吗? - Mike Eason
我刚试了一下,使用ContentControl或ContentPresenter似乎没有任何区别。 - Nick
1个回答

8
将您的数据模板添加到字典中。似乎需要一个默认样式,应用程序资源才能使用它。请参考以下链接以了解更多信息。datatemplate in app.xaml is not getting picked up without any styles? 在XAML中创建每个对象时,如果存在默认样式(即具有Type键的样式),则应该应用该样式。正如您所想象的那样,有几种性能优化方法可以使这种(暗示)查找尽可能轻量级。
其中之一是,除非将其标记为“包含默认样式”,否则我们不会查看资源字典。但是存在一个错误:如果所有默认样式都嵌套在合并的字典中三层深(或更深),则顶层字典不会被标记,因此搜索会跳过它。解决方法是在根字典中将某个内容设置为默认样式。
然后,请参考以下代码。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:vm="clr-namespace:SQ15Mar2015_Learning">
<DataTemplate DataType="{x:Type vm:ViewModel}">
    <DockPanel>
        <TextBox Text="{Binding Path=Name,UpdateSourceTrigger=PropertyChanged}">
        </TextBox>
    </DockPanel>
</DataTemplate>

<Application x:Class="SQ15Mar2015_Learning.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:vm="clr-namespace:SQ15Mar2015_Learning">
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

或者

  <Application.Resources>
    <DataTemplate DataType="{x:Type vm:ViewModel}">
        <DockPanel>
            <TextBox Text="{Binding Path=Name,UpdateSourceTrigger=PropertyChanged}">
            </TextBox>
        </DockPanel>
    </DataTemplate>
    <Style TargetType="{x:Type Rectangle}" />
</Application.Resources>

class ViewModel : INotifyPropertyChanged
{
    private string myVar;
    public string Name
    {
        get { return myVar; }
        set
        {
            if (value != myVar)
            {
                myVar = value;
                OnPropertyChanged("Name");
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        ViewModel oVM = new ViewModel { Name = "Loki" };
        MainWindow oVW = new MainWindow();
        oVW.DataContext = oVM;
        oVW.ShowDialog();
    }
}

<Window x:Class="SQ15Mar2015_Learning.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:SQ15Mar2015_Learning"
    Title="MainWindow" Height="350" Width="525" >

    <Grid>
        <ContentControl Content="{Binding }" />
    </Grid>
</Window>

3
为什么在Application.Resources中定义DataTemplate无效,但在单独的文件中定义并合并后却有效呢?这对我来说毫无意义。 - Nick
请查看此链接以获取解释。https://dev59.com/5m445IYBdhLWcg3wiayV - Ayyappan Subramanian
所以...按理说,它应该按我设计的方式工作,但这是一个 bug。我猜这让我感到少点愚蠢。 - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接