日期:2014-05-17  浏览次数:20756 次

|ZYCWPF| 在自定义控件中ZRichTextBox : RichText 为什么GetTemplateChild和FindName都得不到我的控件对像呢?
自定义控件

    public partial class ZRichTextBox : RichTextBox
    {
        static ZRichTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ZRichTextBox), new FrameworkPropertyMetadata(typeof(ZRichTextBox)));
        }

        public ZRichTextBox()
        {
            this.DataContext = new ViewModel.ZRichTextBoxViewModel(this);
            var colorPicker = this.FindName("fontColorPicker");
            var colorPicker1 = this.GetTemplateChild("fontColorPicker");
        }
}

模版是写在Themes/Generic.xaml里面的
这里都得不到控件的实例

这是为什么呢?
谢谢
------解决方案--------------------
要写在OnApplyTemplate方法里,等到模板加载了才能找到
------解决方案--------------------
写在Loaded事件中看看。
------解决方案--------------------
功能实现上是对的,没问题。

如果是我的话,我会把对ColorPicker注册事件放到custom control控件类中,直接写在OnApplyTemplate中:
colorPicker.SelectColorCompleted += viewModel.ColorPicker_SelectColorCompleted;

从MVVM的角度讲,你在ViewModel中访问了ui上的元素,是违反它的规则的。
相反在code behind中访问vm,这是允许的。

而且,在写custom control的时候,其实并不存在code behind,这个类文件就是自定义控件本身了,而xaml只是控件的呈现模板。事实上,generic.xaml是缺省模板,还可以定义其它theme样式下的各种模板。
所以概念上custom control是“lookless”的,这个上次也提到过。

MVVM最适合的场合是解决业务/界面直接解偶的问题,而UserControl, custom control大多数其实只是和UI相关。并不包括业务层,特别是custom control, 我觉得它就应该设计成单一功能的UI模块,所以既然没有business model,就没有必要用mvvm。

你看color picker也没有用view model。当然也有用vm的例子:FindReplaceDialog(不过我觉得把FindReplaceMgr看成一个组件,把FindReplaceDialog看成它用到的一个对话框更合适)。
所以我觉得可以根据需要和具体情况灵活掌握,不必太死板了。层次分的越多,阅读代码、修改维护其实都更复杂,要权衡使用。