Проблемы с пользовательскими элементами управления и привязки - PullRequest
0 голосов
/ 15 октября 2011

В настоящее время я создаю кучу общих элементов управления, которые в основном просто расширяют стандартные элементы управления Silverlight, добавляя метку и тому подобное ... Но мне трудно заставить работать некоторые привязки ... Ниже Вот несколько примеров того, что в настоящее время не работает:

UPDATE:

Вот еще один контекст, чтобы помочь понять проблему:

public class ComboboxField : Field
{

    public string SelectedValuePath
    {
        get { return (string)this.GetValue(SelectedValuePathProperty); }
        set { this.SetValue(SelectedValuePathProperty, value); }
    }
    public static readonly DependencyProperty SelectedValuePathProperty =
    DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(ComboboxField), new PropertyMetadata(string.Empty));


    public string DisplayMemberPath
    {
        get { return (string)this.GetValue(DisplayMemberPathProperty); }
        set { this.SetValue(DisplayMemberPathProperty, value); }
    }
    public static readonly DependencyProperty DisplayMemberPathProperty =
      DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(ComboboxField), new PropertyMetadata(string.Empty, null));



    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)this.GetValue(ItemsSourceProperty); }
        set { this.SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty =
    DependencyProperty.Register("ItemsSource", typeof(Object), typeof(ComboboxField), new PropertyMetadata(new List<object>()));



    public object SelectedValue 
    {
        get { return (object)GetValue(SelectedValueProperty); }
        set { SetValue(SelectedValueProperty, value); }
    }

    public static readonly DependencyProperty SelectedValueProperty =
        DependencyProperty.Register("SelectedValue", typeof(object), typeof(ComboboxField), new PropertyMetadata(null, (s, e) => { s.SetValue(Field.ValueProperty, SelectedValueProperty);}));

    #region Ctors
    public ComboboxField(FieldDescription fieldDescription, Form parentForm) : base(fieldDescription, parentForm)
    {
        this.Template = Application.Current.Resources["ComboBoxDefaultTemplate"] as ControlTemplate;
    }

    public ComboboxField() : base(new FieldDescription(Guid.NewGuid(), "ComboboxField1", FieldType.Collection), null)
    {
        this.Template = Application.Current.Resources["ComboBoxDefaultTemplate"] as ControlTemplate;
    }
    #endregion

}

Шаблон управления: (удалены некоторые ненужные вещи)

<ControlTemplate x:Name="ComboBoxDefaultTemplate" TargetType="my:ComboboxField">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="{TemplateBinding LabelColumnWidth}" />
                    <ColumnDefinition Width="{TemplateBinding FieldColumnWidth}" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0" Style="{TemplateBinding TitleStyle}" Text="{TemplateBinding Title}"></TextBlock>
                <TextBlock Text="*" Grid.Row="0" Grid.Column="0" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Required, Converter={StaticResource boolToVisibility}}" Width="5" />
                <TextBlock Grid.Row="1" Grid.Column="0" Style="{TemplateBinding SummaryStyle}" Text="{TemplateBinding Summary}" Grid.ColumnSpan="2"></TextBlock>
<ComboBox Style="{TemplateBinding FieldStyle}" Grid.Row="0" Grid.Column="1"
                          ItemsSource="{TemplateBinding ItemsSource}" 
                          SelectedValue="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValue, Mode=TwoWay}" 
                          SelectedValuePath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValuePath, Mode=TwoWay}" 
                          DisplayMemberPath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisplayMemberPath, Mode=TwoWay}"></ComboBox>
            </Grid>
        </ControlTemplate>

Как я пытаюсь это использовать:

<cc:ComboboxField Grid.Row="10" TitleStyle="{StaticResource labelStyle}" 
                                  Title="Countries" ItemsSource="{Binding Countries}" 
                                  SelectedValuePath="CountryId" DisplayMemberPath="CountryId" 
                                  SelectedValue="{Binding Path=SelectedCountry, Mode=TwoWay}" />

Что я здесь не так делаю?

1 Ответ

1 голос
/ 16 октября 2011

Я сразу вижу пару проблем с вашими свойствами зависимости.

Во-первых, у меня есть золотое правило для работы со свойствами зависимостей, которое нарушает ваш код:

Получатель свойства CLR должен содержать только вызов GetValue, а установщик должен содержать только вызов SetValue.

Например, свойство SelectedValuePath должно выглядеть следующим образом:

public string SelectedValuePath
{
    get { return (string)this.GetValue(SelectedValuePathProperty); }
    set { this.SetValue(SelectedValuePathProperty, value); }
}

Silverlight не вызывает ваше свойство, если оно хочет изменить значение свойства зависимости с помощью привязки, анимации или стилей. Если вы сбросите точки останова на любом из сеттеров, вы обнаружите, что они не будут попадать так часто, как вы могли бы ожидать.

Вы можете связать вместе два свойства зависимостей без класса на каждом конце, который должен реализовать INotifyPropertyChanged. Я предполагаю, что ваш NotifyPropertyChanged метод вызывает событие PropertyChanged, которое вы должны удалить.

Кроме того, если вы хотите, чтобы свойство Value устанавливалось на значение свойства SelectedValue каждый раз, когда последнее изменяется, вам нужно добавить PropertyChangedCallback к свойству зависимости SelectedValue.

Во-вторых, неправильные регистрации свойств зависимостей для SelectedValuePathProperty, DisplayMemberPathProperty и ItemsSourceProperty. Все они указывают свой класс владельца как Field, когда они принадлежат классу ComboboxField.

Наконец, вы говорите, что вы

с трудом заставляет работать некоторые привязки

Вы не говорите нам точно, в чем ваша проблема. Что вы ожидаете от кода и что он на самом деле делает? Учитывая, что у меня нет ни ваших классов Form, Field и FieldDescription, ни вашего перечисления FieldType, я не могу запустить ваш код, поэтому я больше не могу вам помочь.

...