Andrey A. Eroshenko Ответов: 0

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


Всем привет.

У меня есть пользовательский элемент управления WPF, помещенный в сетку. Существует несколько стандартных элементов управления wpf, размещенных в одной сетке. Мой пользовательский элемент управления имеет свойство привязанной зависимости. Родительская сетка имеет datatrigger на видимости свойства и срабатывает, когда DataContext не равен null.

Использование моего пользовательского элемента управления:

<Grid Margin="5" DataContext="{Binding DetailedView}" >
    <Grid.Resources>
        <Style TargetType="{x:Type Grid}">
            <Setter Property="Visibility" Value="Visible"/>
                <Style.Triggers>
                     <DataTrigger Binding="{Binding}" Value="{x:Null}">
                          <Setter Property="Visibility" Value="Collapsed"/>
                     </DataTrigger>
                </Style.Triggers>
            </Style>
    </Grid.Resources>
    <!- ... -->
    <!-- Grid layout -->
    <!-- ... -->
    <Grid Grid.Column="1" Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="320"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="32"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <!-- My Custom control -->
        <controls:RatingControl x:Name="RcMangaRating" Grid.Column="1" Grid.Row="0" Value="{Binding Rating}" Size="24" Maximum="10" HorizontalAlignment="Right"/>
        <!-- Standard WPF control which have same binding as custom control -->
        <TextBlock Grid.Column="1" Grid.Row="1" FontSize="12" VerticalAlignment="Top" Text="{Binding Rating, StringFormat='{}Rating: {0:F2} from 10'}" Margin="0,5,5,0" HorizontalAlignment="Right"/>
    </Grid>
</Grid>


Таким образом, когда видимость изменилась с свернутой на видимую, привязка для пользовательского элемента управления не работает, но для стандартного элемента управления привязка работает нормально. http://i.stack.imgur.com/bzZc7.png[^]

Но когда видимость сетки установлена на видимую и не меняется привязка для пользовательского элемента управления, он работает нормально. http://i.stack.imgur.com/ny5EH.png[^]

Область пользовательского стиля управления:

<Rectangle Grid.Row="0" Height="{TemplateBinding Width}" Width="{TemplateBinding Height}">
    <Rectangle.Style>
        <Style>
             <Setter Property="Rectangle.OpacityMask">
                <Setter.Value>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                        <GradientStop Color="Black" Offset="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}"/>
                        <GradientStop Color="Transparent" Offset="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style>
    </Rectangle.Style>
</Rectangle>


Что я уже пробовал:

Я удаляю триггер на свойстве видимости и все привязки работают нормально

<Grid Margin="5" DataContext="{Binding DetailedView}" >
    <!-- ... -->
    <!-- Grid layout -->
    <!-- ... -->
    <Grid Grid.Column="1" Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="320"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="32"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <!-- My Custom control -->
        <controls:RatingControl x:Name="RcMangaRating" Grid.Column="1" Grid.Row="0" Value="{Binding Rating}" Size="24" Maximum="10" HorizontalAlignment="Right"/>
        <!-- Standard WPF control which have same binding as custom control -->
        <TextBlock Grid.Column="1" Grid.Row="1" FontSize="12" VerticalAlignment="Top" Text="{Binding Rating, StringFormat='{}Rating: {0:F2} from 10'}" Margin="0,5,5,0" HorizontalAlignment="Right"/>
    </Grid>
</Grid>


У вас есть какие-нибудь идеи, в чем проблема?

--
Заранее благодарю вас.

Проблема решена

Решение:

Так, во-первых, существует проблема заключалась в объект onapplytemplate в моей власти. Я получаю TemplatePart в этом методе и инициализирую некоторые поля в элементе управления:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    _starItems = (ItemsControl)GetTemplateChild("PART_StarItems");
    if (_starItems == null) return;

    var values = Enumerable.Range(0, (int)Maximum).Select(r => 0.0).ToList();
    _starValues = new ObservableCollection<double>(values);
}


Затем в обратном вызове OnChangeValue применяет _starValues к _starItems. Но в первый раз OnApplyTemplate после инициализации не вызывается (он вызывает после OnChangeValue и т. д.), а _starItems был равен null:

RatingControl control = d as RatingControl;
if (control == null) return;
if (control._starItems == null) return; // Here was problem

/* Update values in _starValues */
_starItems.ItemsSource = _starValues;


Итак, я создал новые частные значения DependecyProperty (такие же, как _starValues) и привязал их к ItemsSource моего элемента управления, а также удалил TemplatePart и ненужные поля.

Исходный код[^]

Стиль шаблона управления[^]

Извините, проблема была не в контрольном шаблоне (как я изначально думал), а в моем коде есть реализация привязки для ItemsSource. По этой причине я изначально публикую только код XAML. Спасибо.

Спасибо моему руководителю за помощь и Совет

0 Ответов