Привязка свойства зависимости не обновляет цель - PullRequest
1 голос
/ 17 июня 2010

У меня есть свойство пользовательской зависимости:

    public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("HeaderProperty", typeof(string), typeof(RadAdjustableSlider));
    public string Header
    {
        get
        {
            return (string)GetValue(HeaderProperty);
        }
        set
        {
            SetValue(HeaderProperty, value);
        }
    }

У меня тогда есть привязка в моем xaml:

<TextBlock Name="txtHeader" Text="{Binding ElementName=main, Path=Header, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />

Обратите внимание, что у меня также есть это в объявлении в верхней части файла xaml:

         x:Name="main"

Наконец, у меня есть этот конструктор:

    public RadAdjustableSlider()
    {
        InitializeComponent();
        this.Header = "Header";
    }

Когда я помещаю этот элемент управления в другой родительский элемент управления, текстовый блок Заголовок остается пустым. Почему?

Редактировать: В этом блоге говорится, что правильный способ сделать это - предоставить ValidateValueCallback в вызове DependencyProperty.Register, но это выглядит довольно непросто Не объясните, как свойства зависимостей ведут себя при взаимодействии с внешними элементами управления. Я действительно собираюсь написать функции обратного вызова для всех моих свойств зависимости?

Ответы [ 2 ]

1 голос
/ 18 июня 2010

Уже есть фреймворк HeaderedContentControl и HeaderedItemsControl ...

Но если вы действительно хотите создать свой собственный, то вам, вероятно, следует использовать TemplateBinding.Вместо этого попробуйте что-то вроде этого:

class MyHeaderedControl : ContentControl
{
  public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
    "Header",
    typeof(object),
    typeof(MyHeaderedControl),
    new PropertyMetadata());

  public MyHeaderedControl()
  {
    this.DefaultStyleKey = typeof(MyHeaderedControl);
  }
}

Затем в вашем проекте создайте файл в "\ Themes \ Generic.xaml".Это файл со специальным именем, который должен находиться в корне проекта, а затем в папке «Темы».Он должен содержать ResourceDictionary.

<ResourceDictionary
  xmlns="..."
  xmlns:x="..."
  xmlns:c="MyControlLibrary1"
  >
  <Style TargetType="{x:Type c:MyHeaderedControl>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type c:MyHeaderedControl}">
          <StackPanel>
            <ContentControl Content="{TemplateBinding Header}" />
            <ContentPresenter /> 
          </StackPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Кроме того, в вашем AssemblyInfo.cs добавьте этот атрибут, если его там еще нет:

[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, 
       ResourceDictionaryLocation.SourceAssembly)]

Так что для обзора.Общая идея состоит в том, чтобы создать некоторый тип логического элемента управления, в котором у вас есть свойства, события, логика и т. Д. Затем в той же сборке вы предоставляете темы по умолчанию.Вот как элементы управления будут отображаться по умолчанию.В любом месте, где используются элементы управления, шаблоны по умолчанию могут быть переопределены, а определенные шаблоны могут быть переопределены как обычно.

Так что это самый безболезненный способ добавить пользовательский контент, подобный этому, в свои собственные элементы управления!Попробуйте один раз, и это будет иметь смысл, а не чувствовать себя грязным.Если вы делаете больше элементов управления, просто продолжайте добавлять их в файл Generic.xaml.

0 голосов
/ 29 октября 2011

Как упомянуто выше в justin.m.chase, пользовательский элемент управления, вероятно, является лучшим способом, но UserControls - это распространенный сценарий, поэтому я все равно добавлю свой 2c.

UserControl не устанавливает для вас свойство DataContent, и поэтому все ваши привязки внутри XAML UserControl преобразуются в DataContent, в котором вы разместили элемент управления.

Чтобы изменить это поведение, либо установите свойство DataContext в конструкторе usercontrol:

public RadAdjustableSlider()
{
    InitializeComponent();
    this.Header = "Header";

    this.DataContext = this;
}

, а затем связать так:

<TextBlock Text="{Binding Header}" />

или не устанавливайте DataContext и связывайте так:

<TextBlock Text="{Binding Header, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ns:RadAdjustableSlider}}}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...