You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI3 WinRT/C++原生桌面应用无法创建Xaml UserControl

WinUI3 C++/WinRT 自定义UserControl编译错误排查

问题背景

创建极简WinUI3 WinRT/C++桌面(空白、打包)项目并添加UserControl后,原本可正常编译运行。为实现DependencyProperty功能修改代码时出现以下问题:

  • 尝试给实现类添加UserControl继承时,触发静态断言错误:

static_assert failed: 'Class must derive from implements<> or ClassT<> where the first template parameter is the derived class name, e.g. struct D : implements<D, ...>'

  • 尝试添加DependencyProperty时,提示OneWay模式需实现INotifyPropertyChange,但添加该接口继承时又提示已是基类。

现有代码文件

CalcButton.idl

namespace ThirdCppAppv3
{
    [default_interface]
    runtimeclass CalcButton : Microsoft.UI.Xaml.Controls.UserControl
    {
        CalcButton();
    }
}

CalcButton.xaml

<?xml version="1.0" encoding="utf-8"?>
<UserControl
    x:Class="ThirdCppAppv3.CalcButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ThirdCppAppv3"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button x:Name="myButton" Click="myButton_Click" Content="Custom Button"></Button>
    </StackPanel>
</UserControl>

CalcButton.xaml.h

#pragma once

#include "CalcButton.g.h"

namespace winrt::ThirdCppAppv3::implementation
{
    struct CalcButton : CalcButtonT<CalcButton, Microsoft::UI::Xaml::Controls::UserControl>
    {
        CalcButton();

        void myButton_Click(IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&);

    };
}

namespace winrt::ThirdCppAppv3::factory_implementation
{
    struct CalcButton : CalcButtonT<CalcButton, implementation::CalcButton>
    {
    };
}

CalcButton.xaml.cpp

#include "pch.h"
#include "CalcButton.xaml.h"
#include "CalcButton.g.cpp"

using namespace winrt;
using namespace Microsoft::UI::Xaml;

namespace winrt::ThirdCppAppv3::implementation
{
    CalcButton::CalcButton()
    {

    }

    void CalcButton::myButton_Click(IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
    {

    }

}

解决方案

1. 修复继承结构错误

C++/WinRT中,工具生成的CalcButtonT基类已自动关联idl中声明的UserControl基类,实现类无需显式继承Microsoft::UI::Xaml::Controls::UserControl。修改CalcButton.xaml.h中的实现类定义:

namespace winrt::ThirdCppAppv3::implementation
{
    // 移除第二个模板参数,仅保留派生类名称
    struct CalcButton : CalcButtonT<CalcButton>
    {
        CalcButton();

        void myButton_Click(IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&);
    };
}

2. 初始化XAML内容

构造函数中必须调用InitializeComponent(),否则XAML控件不会加载,这是易忽略的关键步骤:

CalcButton::CalcButton()
{
    InitializeComponent(); // 添加此行代码
}

3. DependencyProperty相关问题说明

  • 自定义DependencyProperty无需手动实现INotifyPropertyChanged,DependencyProperty本身已支持属性变更通知,OneWay绑定模式对其天然兼容,之前的错误提示是继承结构混乱导致的编译干扰。
  • 若要添加自定义DependencyProperty,可参考以下示例(以添加ButtonText属性为例):
    在idl中添加属性声明:
    [default_interface]
    runtimeclass CalcButton : Microsoft.UI.Xaml.Controls.UserControl
    {
        CalcButton();
        static Microsoft.UI.Xaml.DependencyProperty ButtonTextProperty{ get; };
        string ButtonText{ get; set; };
    }
    
    在CalcButton.xaml.cpp中实现属性逻辑:
    namespace winrt::ThirdCppAppv3::implementation
    {
        Microsoft::UI::Xaml::DependencyProperty CalcButton::ButtonTextProperty()
        {
            static auto property = Microsoft::UI::Xaml::DependencyProperty::Register(
                L"ButtonText",
                winrt::xaml_typename<winrt::hstring>(),
                winrt::xaml_typename<ThirdCppAppv3::CalcButton>(),
                Microsoft::UI::Xaml::PropertyMetadata{ winrt::box_value(L"Custom Button") }
            );
            return property;
        }
    
        winrt::hstring CalcButton::ButtonText()
        {
            return winrt::unbox_value<winrt::hstring>(GetValue(ButtonTextProperty()));
        }
    
        void CalcButton::ButtonText(winrt::hstring const& value)
        {
            SetValue(ButtonTextProperty(), winrt::box_value(value));
        }
    }
    
    最后在XAML中绑定该属性:
    <Button x:Name="myButton" Click="myButton_Click" Content="{x:Bind ButtonText, Mode=OneWay}"></Button>
    

内容的提问来源于stack exchange,提问作者Peter Vermilye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:08:14