Windows phone 8.1 自定义控件的某些部分

Windows phone 8.1 自定义控件的某些部分,windows-phone-8.1,windows-store-apps,winrt-xaml,win-universal-app,Windows Phone 8.1,Windows Store Apps,Winrt Xaml,Win Universal App,我正在开发一个通用窗口SDK SDK的主要入口点是一个UserControl派生类,它公开了一些功能 我们不允许用户完全改变外观,这就是为什么我不喜欢CustomControl+generic.xaml+模板部件方法 但是,我们希望允许自定义一些子项。就像我们控制的三个不同的按钮一样。我想提供合理的默认样式/模板/内容,但我希望我的用户能够完全重新设计这些子项,以防他们需要。或者,如果他们想这样做,只需更改背景色 最好的办法是什么 暴露我的控件的属性Style按钮1style 是否公开我的控件的

我正在开发一个通用窗口SDK

SDK的主要入口点是一个UserControl派生类,它公开了一些功能

我们不允许用户完全改变外观,这就是为什么我不喜欢CustomControl+generic.xaml+模板部件方法

但是,我们希望允许自定义一些子项。就像我们控制的三个不同的按钮一样。我想提供合理的默认样式/模板/内容,但我希望我的用户能够完全重新设计这些子项,以防他们需要。或者,如果他们想这样做,只需更改背景色

最好的办法是什么

  • 暴露我的控件的属性
    Style按钮1style
  • 是否公开我的控件的属性(依赖项?)
    ControlTemplate按钮1模板
  • 是否公开我的控件的(依赖项?)属性
    DataTemplate按钮1contenttemplate
  • 这些的组合
  • 还有别的办法吗
  • SDK是可移植的,需要支持Windows 8.1和10,包括商店和手机

    更新:我知道数据绑定工作需要依赖属性。我不知道我的用户是否会使用数据绑定。 我不需要动画

    我期待的用例如下:

  • 大多数客户应该对默认外观感到满意——对于他们来说,我只需要提供合理的默认外观
  • 有些人希望更改某些子控件的颜色或边距
  • 有些人会用他们的自定义图标替换我们的图标
  • 有些人将完全返工我们的按钮的样式和模板

  • 我想让他们在MS Blend中做2-4个,仅在XAML中。怎么做?

    @Soons,这里有很多变量。而且,尽管许多StackOverflow的书呆子对开发人员在一个问题中问多个问题感到非常恼火,但我认为我们可以一起工作来得到您的答案

    首先,我认为你应该回顾一下我关于这个主题的文章。它关注于用户控件中的双向绑定,诚然,这是一个技巧

    其次,我认为理解ControlTemplate绑定、属性动画和绑定以及DataTemplate作用域很重要。我在“微软虚拟学院”的一门课程中对这个话题进行了深入的探讨

    对大多数问题的简短回答是,依赖性属性是您所需要的。因为您使用Windows 8标记了问题,所以利用属性元数据中定义的已更改事件非常重要。同样,这是在文章中

    最后,我已经编写了一个从用户控件派生的重要控件,因此我可以确认您想要实现的肯定是可能的。如果你想查看我的代码,看看我们是否在做任何你想偷的事情,你也可以这么做


    祝你好运。

    @Soons,这里有很多变量。而且,尽管许多StackOverflow的书呆子对开发人员在一个问题中问多个问题感到非常恼火,但我认为我们可以一起工作来得到您的答案

    首先,我认为你应该回顾一下我关于这个主题的文章。它关注于用户控件中的双向绑定,诚然,这是一个技巧

    其次,我认为理解ControlTemplate绑定、属性动画和绑定以及DataTemplate作用域很重要。我在“微软虚拟学院”的一门课程中对这个话题进行了深入的探讨

    对大多数问题的简短回答是,依赖性属性是您所需要的。因为您使用Windows 8标记了问题,所以利用属性元数据中定义的已更改事件非常重要。同样,这是在文章中

    最后,我已经编写了一个从用户控件派生的重要控件,因此我可以确认您想要实现的肯定是可能的。如果你想查看我的代码,看看我们是否在做任何你想偷的事情,你也可以这么做

    祝你好运。

    实施了#1,多多少好

  • 设置这些零件的样式/模板,将这些样式/模板放在单独的资源字典“DefaultStyles”中
  • 创建一个。这样做是为了避免疯狂的“ms appx://”URI,而是通过类名引用字典
  • 在用户控件代码中,为控件的可自定义部分添加几个类型为“Style”的依赖项属性
  • 在用户控件代码中的构造函数中,将控件根元素(而不是控件本身)的数据上下文设置为
    this
  • 在用户控件XAML中,包括DefaultStyles资源:

    <ResourceDictionary.MergedDictionaries>
        <local:DefaultStyles />
    </ResourceDictionary.MergedDictionaries>
    
  • 最后,在客户端应用程序的页面中:

    <ResourceDictionary.MergedDictionaries>
        <sdk:DefaultStyles />
    </ResourceDictionary.MergedDictionaries>
    <!-- Debug code: override a single property -->
    <Style x:Key="sss" TargetType="Button" BasedOn="{StaticResource MyButtonDefaultStyle}">
        <Setter Property="Foreground" Value="Green" />
    </Style>
    
    <sdk:TheControl MyButtonStyle={StaticResource sss} />
    
    
    
  • 这样,一切都可以开箱即用,我的用户可以在不复制粘贴XAML页面的情况下调整单个边距或颜色,或者完全忽略我提供的样式/模板并创建他们自己的样式/模板

    我想知道有没有更简单的方法

    “允许用户部分或完全覆盖样式”这项任务听起来并不难完成

    更新:由于某些原因,在windows phone 8.1上,您无法在样式中设置
    内容
    属性(没有错误,只是没有效果)。幸运的是,您可以改为设置
    ContentTemplate
    属性,该属性似乎在所有平台上都适用。

    Implemented#1,多多少少正常

  • 设置这些零件的样式/模板,将这些样式/模板放在单独的资源字典“DefaultStyles”中
  • 创建一个。这样做是为了避免疯狂的“ms appx://”URI,而是通过类名引用字典
  • 在用户控件代码中,为控件的可自定义部分添加几个类型为“Style”的依赖项属性
  • 在用户控件代码的构造函数中,设置控件根元素的数据上下文(但不设置cont)
    <UserControl>
        <Grid Background="{x:Bind MyBackground, FallbackValue=White}">
            <TextBlock Text="{x:Bind MyText, FallbackValue=DesigntimeValue }" />
        </Grid>
    </UserControl>
    
    public sealed partial class MyUserControl : UserControl, INotifyPropertyChanged
    {
        public MyUserControl()
        {
            InitializeComponent();
        }
    
        Brush _MyBackground = new SolidColorBrush(Colors.Blue);
        public Brush MyBackground { get { return _MyBackground; } set { Set(ref _MyBackground, value); } }
    
        string _MyText = "Default value";
        public string MyText { get { return _MyText; } set { Set(ref _MyText, value); } }
    
        #region INotifyPropertyChanged
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (!Equals(storage, value))
            {
                storage = value;
                RaisePropertyChanged(propertyName);
            }
        }
    
        void RaisePropertyChanged([CallerMemberName] string propertyName = null) =>
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
        #endregion  
    }
    
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <local:MyUserControl MyBackground="Yellow" MyText="JerryNixon" />
    </Grid>