none
使用2重binding的自定义控件抛异常 RRS feed

  • 问题

  • 自定义控件MyBaseCtl.xaml

                <Grid>
                    <!-- BasePage为MyBaseCtl.xaml page的名字-->
                    <Rectangle x:Name="BaseRect" Fill="{Binding Path=BgRectClr,ElementName=BasePage}"/>
                </Grid>

    MainPage.xaml

    <local:MyBaseCtl x:Name="testBaseCtl" BgRectClr="{Binding}"/>

    MainPage.xaml.cpp

    testBaseCtl->DataContext="Orange";

    运行后抛异常:

    请问这个是不是在初始化的时候在没有传入值的时候,自定义控件就开始初始化,所以抛异常,我现在是在自定义控件的Loaded完成之后,再在代码中设置属性,有没有其它比较好的解决方案?

    2012年7月25日 1:44

答案

  • 只有依赖属性才可以接受绑定,所以你的BgClr必须定义为依赖属性。参考:http://msdn.microsoft.com/en-us/library/windows/apps/hh920267.aspx

    BlankCtl头文件:

    	[Windows::UI::Xaml::Data::Bindable]
    	public ref class BlankCtl sealed
    	{
    	private:
    		static Windows::UI::Xaml::DependencyProperty^ s_BgClrProperty;
    		
    	public:
    		BlankCtl();
    		property Windows::UI::Xaml::Media::Brush^ BgClr
    		{
    			void set(Windows::UI::Xaml::Media::Brush^ value)
    			{
    				SetValue(BgClrProperty, value);
    			} 
    			Windows::UI::Xaml::Media::Brush^ get()
    			{
    				return (Windows::UI::Xaml::Media::Brush^)GetValue(BgClrProperty);
    			}
    		}
    		static property Windows::UI::Xaml::DependencyProperty^ BgClrProperty 
    		{
    			Windows::UI::Xaml::DependencyProperty^ get() { return s_BgClrProperty; }
    		}
    	protected:
    		virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
    	};

    Cpp文件:

    using namespace Windows::UI::Xaml::Interop;
    DependencyProperty^ BlankCtl::s_BgClrProperty = 
    	DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr);
    ....


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    • 已标记为答案 pjfitren 2012年7月26日 8:41
    2012年7月26日 7:37
    版主
  • 看到错误了,你需要把 BlankCtl::s_BgClrProperty = DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr); 移出构造函数,他是一个静态字段的初始化,所以直接放在cpp 下即可:

    #include "pch.h"
    #include "BlankCtl.xaml.h"
    
    using namespace testCustomCtl;
    
    using namespace Platform;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Controls::Primitives;
    using namespace Windows::UI::Xaml::Data;
    using namespace Windows::UI::Xaml::Input;
    using namespace Windows::UI::Xaml::Media;
    using namespace Windows::UI::Xaml::Navigation;
    using namespace Windows::UI::Xaml::Interop;
    
    // “空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=234238 上提供
    
    DependencyProperty^ BlankCtl::s_BgClrProperty = DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr);
    
    BlankCtl::BlankCtl()
    {
    	InitializeComponent();
    }
    
    /// <summary>
    /// 在此页将要在 Frame 中显示时进行调用。
    /// </summary>
    /// <param name="e">描述如何访问此页的事件数据。Parameter
    /// 属性通常用于配置页。</param>
    void BlankCtl::OnNavigatedTo(NavigationEventArgs^ e)
    {
    	(void) e;	// Unused parameter
    }


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年7月27日 6:18
    版主
  • No,以来属性规则必须要提供一个静态的DependencyProperty 的字段,不要去掉。虽然去掉在你的程序中没有问题,但是在其他地方比如动画,和依赖属性访问时会有问题。

    可以直接用字符串是因为这里用了Brush 去定义你的BgClr Brush在XAML中有String to Brush的转换器。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    • 已标记为答案 pjfitren 2012年7月26日 9:16
    2012年7月26日 9:06
    版主

全部回复

  •  SolidColorBrush^ Orange = ref new SolidColorBrush(Windows::UI::Colors::Orange);
     testBaseCtl->DataContext = Orange;

    一个字符串在绑定中是不会被转换成Brush的,只有直接在XAML写String , XAML解析的时候会对Brush类型进行String to Brush的转换。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年7月25日 8:56
    版主
  • 谢谢!

    照你的做了,我的为什么还是要抛异常呐?帮我看看:http://www.kuaipan.cn/file/id_44708732650652710.htm,谢谢!

    2012年7月25日 11:28
  • 只有依赖属性才可以接受绑定,所以你的BgClr必须定义为依赖属性。参考:http://msdn.microsoft.com/en-us/library/windows/apps/hh920267.aspx

    BlankCtl头文件:

    	[Windows::UI::Xaml::Data::Bindable]
    	public ref class BlankCtl sealed
    	{
    	private:
    		static Windows::UI::Xaml::DependencyProperty^ s_BgClrProperty;
    		
    	public:
    		BlankCtl();
    		property Windows::UI::Xaml::Media::Brush^ BgClr
    		{
    			void set(Windows::UI::Xaml::Media::Brush^ value)
    			{
    				SetValue(BgClrProperty, value);
    			} 
    			Windows::UI::Xaml::Media::Brush^ get()
    			{
    				return (Windows::UI::Xaml::Media::Brush^)GetValue(BgClrProperty);
    			}
    		}
    		static property Windows::UI::Xaml::DependencyProperty^ BgClrProperty 
    		{
    			Windows::UI::Xaml::DependencyProperty^ get() { return s_BgClrProperty; }
    		}
    	protected:
    		virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
    	};

    Cpp文件:

    using namespace Windows::UI::Xaml::Interop;
    DependencyProperty^ BlankCtl::s_BgClrProperty = 
    	DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr);
    ....


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    • 已标记为答案 pjfitren 2012年7月26日 8:41
    2012年7月26日 7:37
    版主
  • 谢谢!

    做了一些修改,把static改掉了(不知道这个会有神马影响,我这个例子简单,暂时没有发现问题),不然会连接出错,同时现在注册BgClr之后,就可以在main中直接用"Orange"字符串了,

    BlankCtl.xaml.h

    	[Windows::UI::Xaml::Data::Bindable]
    	public ref class BlankCtl sealed
    	{
    	public:
    		BlankCtl();
    		property Brush^ BgClr{
    			void set(Brush^ value){SetValue(BgClrProperty,value);}
    			Brush^ get(){return (Brush^)GetValue(BgClrProperty);}
    		};
    		property DependencyProperty^ BgClrProperty{
    			DependencyProperty^ get() { return m_BgClrProperty; }
    		};
    
    	protected:
    		virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
    	private:
    		void OnCtlTapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e);
    	private:
    		DependencyProperty^ m_BgClrProperty;
    	};

    BlankCtl.xaml.cpp

    m_BgClrProperty = DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr);

    MainPage.xaml.cpp

    testBaseCtl->DataContext = "Orange";

    2012年7月26日 8:41
  • No,以来属性规则必须要提供一个静态的DependencyProperty 的字段,不要去掉。虽然去掉在你的程序中没有问题,但是在其他地方比如动画,和依赖属性访问时会有问题。

    可以直接用字符串是因为这里用了Brush 去定义你的BgClr Brush在XAML中有String to Brush的转换器。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    • 已标记为答案 pjfitren 2012年7月26日 9:16
    2012年7月26日 9:06
    版主
  • 加成static之后,link出错了

    BlankCtl.xaml.obj : error LNK2001: 无法解析的外部符号 "private: static class Windows::UI::Xaml::DependencyProperty ^ testCustomCtl::BlankCtl::s_BgClrProperty" (BgClrProperty@BlankCtl@testCustomCtl@@0P$AAVDependencyProperty@Xaml@UI@Windows@@$AA)

    .cpp

    BlankCtl::s_BgClrProperty = DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr);
    

    .h

    #pragma once
    
    #include "BlankCtl.g.h"
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Media;
    namespace testCustomCtl
    {
    	/// <summary>
    	/// 可用于自身或导航至 Frame 内部的空白页。
    	/// </summary>
    	[Windows::UI::Xaml::Data::Bindable]
    	public ref class BlankCtl sealed
    	{
    	public:
    		BlankCtl();
    	public:
    		property Brush^ BgClr{
    			void set(Brush^ value){SetValue(BgClrProperty,value);}
    			Brush^ get(){return (Brush^)GetValue(BgClrProperty);}
    		};
    		static property DependencyProperty^ BgClrProperty{
    			DependencyProperty ^ get(){return s_BgClrProperty;};
    		};
    	private:
    		static DependencyProperty ^ s_BgClrProperty;
    	protected:
    		virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
    	private:
    		void OnCtlTapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e);
    	};
    }
    2012年7月26日 11:43
  • 对了,你把你的header 文件里面 private放到你的public前面,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us


    2012年7月27日 3:24
    版主
  • 同样要报错,是不是工程属性或者link中要加某个lib?

    error C3984: “testCustomCtl::BlankCtl”: 非值类型不能具有任何公共数据成员“s_BgClrProperty” (BlankCtl.xaml.cpp)

    我的整个工程,帮忙看看,谢谢!

    http://www.kuaipan.cn/file/id_44708732650652738.htm

    2012年7月27日 5:35
  • 看到错误了,你需要把 BlankCtl::s_BgClrProperty = DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr); 移出构造函数,他是一个静态字段的初始化,所以直接放在cpp 下即可:

    #include "pch.h"
    #include "BlankCtl.xaml.h"
    
    using namespace testCustomCtl;
    
    using namespace Platform;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Controls::Primitives;
    using namespace Windows::UI::Xaml::Data;
    using namespace Windows::UI::Xaml::Input;
    using namespace Windows::UI::Xaml::Media;
    using namespace Windows::UI::Xaml::Navigation;
    using namespace Windows::UI::Xaml::Interop;
    
    // “空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=234238 上提供
    
    DependencyProperty^ BlankCtl::s_BgClrProperty = DependencyProperty::Register("BgClr", Brush::typeid, BlankCtl::typeid, nullptr);
    
    BlankCtl::BlankCtl()
    {
    	InitializeComponent();
    }
    
    /// <summary>
    /// 在此页将要在 Frame 中显示时进行调用。
    /// </summary>
    /// <param name="e">描述如何访问此页的事件数据。Parameter
    /// 属性通常用于配置页。</param>
    void BlankCtl::OnNavigatedTo(NavigationEventArgs^ e)
    {
    	(void) e;	// Unused parameter
    }


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年7月27日 6:18
    版主
  • 汗,不仔细,谢谢!!
    2012年7月27日 6:47