8

我刚刚为我解决了一个大的内存问题,我曾经将我们的“主题”资源字典合并到每个 xaml 文件中,而不仅仅是 app.cs.xaml 中。

但是,在除 App.cs.xaml 之外的每个文件中删除合并后,我丢失了设计时样式/模板。

请注意:这仅适用于合并到我们的 Themes.xaml 中的样式(例如 Color.xaml、Brushes.xaml - 我们为每种样式设置了一个)。直接在 Themes.xaml 中定义的东西(我们没有……)有效。

我看到两个解决方案,

1) 在 XAML 中注释掉合并,当我想使用设计时取消注释。

2)在每个控件的默认ctor中都有这个:(也许只适用于Blend)

#if DEBUG
Resources.MergedDictionaries.Add(
                new ResourceDictionary()
                {
                    Source = new System.Uri(@"RD.xml")
                }
                );
#endif

必须有更好的方法来获得页面和控件的设计时编辑,有人知道吗?

谢谢!

4

6 回答 6

10

Blend 4 支持 Visual Studio 2010 也支持的“设计时资源”。请参阅http://adamkinney.wordpress.com/2010/05/04/design-time-resources-in-expression-blend-4-rc/

它几乎只是一个包含您喜欢的任何 MergedDictionaries 的 ResourceDictionary,并像这样显示在项目文件中(由 Blend 自动添加):

<Page Include="Properties\DesignTimeResources.xaml" Condition="'$(DesignTime)'=='true' OR ('$(SolutionPath)'!='' AND Exists('$(SolutionPath)') AND '$(BuildingInsideVisualStudio)'!='true' AND '$(BuildingInsideExpressionBlend)'!='true')">
  <Generator>MSBuild:Compile</Generator>
  <SubType>Designer</SubType>
  <ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>

效果很好。

于 2011-08-09T18:13:29.913 回答
8

我所做的是添加一个从 ResourceDictionary 继承的类并覆盖源属性以检查 IsInDesignMode 是否为真。

如果是我设置源,否则我将源留空(这有效地防止了字典在运行时被合并)

public class BlendMergedDictionary : ResourceDictionary
{
    public bool IsInDesignMode
    {
        get
        {
            return (bool)DependencyPropertyDescriptor.FromProperty(
                            DesignerProperties.IsInDesignModeProperty,
                            typeof(DependencyObject)
                            ).Metadata.DefaultValue;
        }
    }

    public new Uri Source
    {
        get { return base.Source; }
        set
        {
            if (!IsInDesignMode)
                return;

            Debug.WriteLine("Setting Source = " + value);
            base.Source = value;
        }
    }
}

现在,当我需要在 Blend 中引用字典时,我会像这样在字典中合并

<ResourceDictionary.MergedDictionaries>
            <BlendHelpers:BlendMergedDictionary Source="Foo.xaml" />
</ResourceDictionary.MergedDictionaries>

您仍然必须在每个文件的字典中“合并”,但您不必支付在运行时实际加载字典的代价。合并仅用于支持设计时行为。

于 2009-11-17T00:54:57.023 回答
1

Janes question is actually related to this one, i have the same problem. i've created a subclass of ResourceDictionary like Foovanadil suggested, however at design time this throws a "Uri prefix not recodnized" exception

I get this error even if all the sub class does is assign the base.Source property of ResourceDictionary. If i replace my custom ResourceDictionary with the regular one, it works just fine, so im guessing the cider designer does someting special, perhaps replacing ResourceDictionary with something else

I havent tried this in blend but i do get it in VS2010 (sp1 beta) Can someone confirm that the posted awnser works in vs2010?

-edit-

Its possible that the wpf based designer is tripping up the resource locating logic. I've read elsewhere that pack uris are based on the -executing- assembly, not neccecarily the -local- assembly. i'll report whats i finds

-edit2/solution-

Alright so i managed to get Foovanadil solution to work in VS2010, here is the deal. Turns out i was half right, presumably because the wpf designer in VS2010 is itself written in wpf or to provide a better design experience, ResourceDictionary (or some other class that VS2010 uses instead) behaves diffrently at design time.

It turns out that VS replaces the URI that is entered in the xaml. Attatcing to the VS instance and setting a breakpoint in the setter for Source reveals that the actual value that is getting passed is diffrent from what we expect.

Given the xaml:

<Window.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <local:DesignTimeResourceDictionary Source="myxamlfile.xaml"  />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Window.Resources>

Source is set to

markup://1/file:///c:/PathtoMyapp/MainWindow.xaml#0/myxamlfile.xaml

instead of

/myxamlfile.xaml

This is why we get the exception for invalid uris.

Exactly when and where VS2010 edits URIs this way at design time is not known to me, but it renaming the Source property in DesignTimeResourceDictionary to something else does not solve the problem.

Luckliy there is a workaround. If we change the type of Source from Uri to String, the VS designer does not modify the value. In the setter we then create a Uri and pass it to the base property:

public new String Source {
  get {
    return base.Source.ToString();
  }
  set {
    if( !IsInDesignMode )
      return;
    base.Source = new Uri( value, UriKind.RelativeOrAbsolute );
  }
}

Note also that if you use this approach (or any other that ive found such as using x:class in the resource file and instancing it directly from xaml) will cause styles not to get updated until you build. Using the standard ResourceDictionary will cause the designer to update as soon as you edit the imported resource files (even before you save). This is also an indication that the designer treats ResrouceDictionary diffrently at design time.

Hope someone finds this useful :)

于 2011-01-04T12:58:15.687 回答
0

The script idea doesn't seem like a good idea to me. You'd have so many "fake" revisions in your source control and my guess is that you'd have to spend a lot of time tweaking it.

I've been hoping that VS2010 and Expression Blend 3 will make big improvements in this area. Anyone try out the betas and know?

于 2009-07-24T01:03:41.500 回答
0

另一种方法(我们现在要采用的方法):有一个预构建脚本注释掉所有 XAML 文件中的合并。

使在调试模式下调试内存问题等变得更加困难,但可以完全自动化并修复最终版本的问题。

于 2009-06-15T18:45:38.873 回答
0

您可以在 App.xaml 的资源中添加资源字典,这对我来说非常有用。或者我可能没有得到你。

于 2009-10-22T09:41:54.627 回答