没有 XAML 的 WPF

Posted

技术标签:

【中文标题】没有 XAML 的 WPF【英文标题】:WPF without XAML 【发布时间】:2011-08-09 09:39:12 【问题描述】:

在架构上,我认为 WPF 非常棒。一般来说,我是底层渲染/动画内部工作的忠实粉丝。模板和样式设置的灵活性令人印象深刻。

但我讨厌 XAML - 我觉得它使很多事情复杂化。我已经在大型和小型应用程序中使用过它,并且我发现自己很多次都试图弄清楚如何在 XAML 中做一些基本原则是基本但语法很古怪的事情。不仅如此,我还多次想知道解析/绑定的某些部分有多重。 (我知道它已编译,但我不确定在运行时仍评估多少)

XAML 只是构建和加载可视化树的一种方式。是否有任何框架可以简化以非 XML、基于代码(但仍主要是声明性)的方式构建可视化树?具体来说,我对在保留 MVVM 方法的同时缓解以下任何问题的框架感兴趣:

    强类型绑定。指定 ViewModel 必须符合特定类型。我假设 BaseBinding 在引擎盖下使用反射,我对它的速度有点怀疑,更不用说破坏绑定很烦人。

    更快的绑定,非INotifyPropertyChanged 绑定。似乎可以创建某种BindableProperty<T>,并且绑定可以直接监听它,而不是接收所有 ViewModel 属性更改。并且使用直接回调与字符串参数似乎也是有利的。

    一种不同的资源管理方法;同样,某种类型的强类型字典可能非常好。我几乎希望将样式视为 lambda 或其他捕捉强类型方面的东西。

总之,有没有基于非 XAML、非常适合 MVVM 并且是强类型的框架?

【问题讨论】:

用 JavaFX 度过一个周末,不要回头。 【参考方案1】:

简化?不可以。但是您可以在 XAML 中执行的所有操作都可以在代码中执行。例如,这是一个简单的 Windows Ink 绘图应用程序 - 非常简单:

不保存,不改变任何东西 - 但你可以通过代码。

Sketchpad.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Ink;

public class Sketchpad : Application 

    [STAThread]
    public static void Main()
        var app = new Sketchpad();
        Window root = new Window();
        InkCanvas inkCanvas1 = new InkCanvas();

        root.Title = "Skortchpard";

        root.ResizeMode = ResizeMode.CanResizeWithGrip;
        inkCanvas1.Background = Brushes.DarkSlateBlue;
        inkCanvas1.DefaultDrawingAttributes.Color = Colors.SpringGreen;
        inkCanvas1.DefaultDrawingAttributes.Height = 10;
        inkCanvas1.DefaultDrawingAttributes.Width = 10;

        root.Content = inkCanvas1;
        root.Show();
        app.MainWindow = root;
        app.Run();
    


Sketchpad.csproj

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
  <PropertyGroup>
    <AssemblyName>Simply Sketch</AssemblyName>
    <OutputPath>Bin\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xaml">
      <RequiredTargetFramework>4.0</RequiredTargetFramework>
    </Reference>
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="SketchPad.cs" />
  </ItemGroup>
  <Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
    <Target Name="Clean">
    <Delete Files="$(OutputPath)$(AssemblyName).exe" />
  </Target>
  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

仅此而已。当然,如果你想避免 XAML,这基本上意味着你将不得不编写一堆备用 .NET 代码,所以这取决于你 - 你想在 XAML 中转储这些东西,还是你愿意还是用代码写?

我认为在 VS 中执行此操作的最大好处是您可以获得良好的设计师支持,因此通常很容易直观地看到所有内容的位置和去向。它也可能更少查找文档,有时不得不进行一些飞跃。

但是没有 XAML 的 WPF是可能的

您甚至不需要为此安装 Visual Studio,只需 .NET CLI 和开发人员命令提示符即可。将这两个文件放到一个文件夹中,运行msbuild,然后就可以运行Bin目录下的文件了。

【讨论】:

【参考方案2】:
> non-INotifyPropertyChanged binding.

在您的视图模型或模型中手动实现 INotifyPropertyChanged 需要大量的手动/重复工作。但是我读到了这些替代品

DynamicViewModel: MVVM using POCOs with .NET 4.0:该项目旨在提供一种使用普通旧 CLR 对象 (POCO) 实现模型视图视图模型 (MVVM) 架构模式的方法,同时充分利用 .NET 4.0 动态对象类。 利用 .NET 4.0 和 DynamicObject 类,我们可以创建派生自 DynamicObject 类的类型并在运行时指定动态行为。此外,我们可以在派生类型上实现 INotifyPropertyChanged 接口,使其成为数据绑定的良好候选者。

Update Controls .NET:没有 INotifyPropertyChanged 的​​ WPF 和 Silverlight 数据绑定。它会自动发现依赖关系,因此您不必在视图模型中管理它们。 它适用于 Winforms。使用事件通过代码绑定。

notifypropertyweaver:使用 IL 编织(通过 http://www.mono-project.com/Cecil)将 INotifyPropertyChanged 代码注入属性。

不需要属性 无需参考 不需要基类 支持 .net 3.5、.net 4、Silverlight 3、Silverlight 4 和 Windows Phone 7 支持客户端配置模式

【讨论】:

很酷的项目——但它们都以某种形式或形式在后台实现了 INotifyPropertyChanged。我正在寻找更接近每个属性的侦听器而不是每个对象的侦听器的东西。谢谢!【参考方案3】:

这个问题肯定需要Bling UI Toolkit 的链接。它是一个超级天才的高级库,用于在 WPF 之上进行动画和丰富的 UI 原型设计。与button.Width = 100 - slider.Value 绑定,动画如下:button.Left.Animate().Duration(500).To = label.Right,像素着色器编译器 - 太棒了。

遗憾的是,我认为该项目已不再进行。但是有很多非常聪明的想法值得深思。

【讨论】:

【参考方案4】:

我在无 Xaml 的 WPF 中支持你。我喜欢 WPF 的布局和绑定功能,但我也讨厌 XAML。我希望 WPF 可以用纯 C# 编写,有一些优点:

对象和集合初始化器 可以替换 Xaml 实例化。 (遗憾的是,xaml 更喜欢自上而下而不是按钮向上)。 绑定转换器可能只是 lambda。 样式可能只是在实例化后修改对象的 lambda,没有臃肿的 &lt;Setter&gt; 语法。 DataTemplates 只是在给定对象的情况下创建控件的 lambdas DataTemplateSelectors 只是一个调用其他 DataTemplate 的 DataTemplate lambda。 ItemsControl 将只是一个 Foreach,它接受一个 lambda (DataTemplate) 并在将新项目添加到基础集合时再次调用它。 x:Names 只是变量名。 不需要很多标记扩展 x:静态 x:Type(尤其是复杂的泛型!) UserControls 只是函数。

我认为 WPF 中添加了太多复杂性以允许对其进行设计。从过去的 FrontPage 到 Razor,Web 开发已经输掉了这场战斗。

【讨论】:

你和我在这方面的想法非常相似。我想你可能会发现我为其中一些想法制作的小操场很有趣(但可能不太有用)。我玩弄了将 Fleck 用于 websockets 并在 Canvas 中进行一些简单的渲染。在bitbucket.org/jtrana/crimson 找到它。我得到了一个带有简单绑定的基本框架,一个或两个基本控件,以及一个文本框的一些工作。一切都很简单的实现,但尝试基于 lambda 的绑定等很有趣。只需启动项目并在 Crimson/Communication 中打开 client.html 我同意你在这里所说的一切(至少,我作为非 Windows 工程师所理解的一切),但不幸的是,这也不能回答问题。 我同意,XML 的主要设计目标不是人类可读性和开发人员友好性【参考方案5】:

WPF 没有这样的框架。您在愿望清单中提到的三件事将直接(和不同)替换 WPF 已经提供的组件。此外,用您的版本替换绑定和资源系统会使您喜欢的 WPF(动画、模板等)无法使用,因为它们严重依赖绑定、资源等。

这里有一些建议可以改善您的体验。 1. 学习处理 XAML(我以前也讨厌它的胆量,但现在我习惯了它很棒) 2. 构建您自己的库,让您在代码中轻松创建 UI。毕竟,在 XAML 中完成的所有事情也可以在代码中完成。 3. 如果你真的讨厌 INotifyPropertyChanged,并且想要一个回调而不是使用 DependencyProperty。没有事件让你引发,你可以有一个回调和默认值! 4.) 不要使用 WPF。即使您说您喜欢该架构,但您列出的缺点/想要的“改进”几乎涵盖了所有内容。

【讨论】:

以上是关于没有 XAML 的 WPF的主要内容,如果未能解决你的问题,请参考以下文章

WPF/XAML:使用相同事件的多个控件 - 有没有更简单的方法?

wpf使用mahapps.metro后为啥窗体没有了阴影

WPF 优化 XAML 代码

WPF在XAML中Binding使用StringFormat属性

C# wpf 将xaml打印成pdf并能实现分页,ps:xaml里面是一个FixedPage的控件,请问该怎么做

如何在文件后面没有代码的情况下移动无边框 wpf 窗口