Как настроить связь данных и пользовательскую привязку пользовательского контроля - PullRequest
1 голос
/ 16 марта 2012

Я не понимаю, почему привязка работает для Textbox, но не работает для usercontrol. На изображении ниже вы видите, как это должно работать. Служба может связываться с желтым usercontrol, и этот usercontrol содержит свойство моего собственного класса. В моем случае это свойство называется Email . Проблема в том, что этот Email никогда не привязывается к желтому пользовательскому контролю. Если я заменю usercontrol простым элементом управления * TextBox , он будет работать правильно.

Подскажите, пожалуйста, как заставить работать Переплет?

User control description of binding

Код за Silvelright Главная страница

#Region "UserProfile"

    ''' <summary>
    ''' UserProfile Dependency Property
    ''' </summary>
    Public Shared ReadOnly UserProfileProperty As DependencyProperty = _
        DependencyProperty.Register("UserProfile", GetType(ServiceReference1.UserProfile), GetType(MainPage), _
            New Windows.PropertyMetadata(Nothing, _
                AddressOf OnUserProfileChanged))

    ''' <summary>
    ''' Gets or sets the UserProfile property.  This dependency property 
    ''' indicates ....
    ''' </summary>
    Public Property UserProfile() As ServiceReference1.UserProfile
        Get
            Return CType(GetValue(UserProfileProperty), ServiceReference1.UserProfile)
        End Get
        Set(ByVal value As ServiceReference1.UserProfile)
            SetValue(UserProfileProperty, value)
        End Set
    End Property

    ''' <summary>
    ''' Handles changes to the UserProfile property.
    ''' </summary>
    Private Overloads Shared Sub OnUserProfileChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim target As MainPage = CType(d, MainPage)
        Dim oldUserProfile As ServiceReference1.UserProfile = CType(e.OldValue, ServiceReference1.UserProfile)
        Dim newUserProfile As ServiceReference1.UserProfile = target.UserProfile
        target.OnUserProfileChanged(oldUserProfile, newUserProfile)
    End Sub

    ''' <summary>
    ''' Provides derived classes an opportunity to handle changes to the UserProfile property.
    ''' </summary>
    Protected Overridable Overloads Sub OnUserProfileChanged(ByVal oldUserProfile As ServiceReference1.UserProfile, ByVal newUserProfile As ServiceReference1.UserProfile)
        Me.DataContext = newUserProfile

    End Sub

#End Region

при отслеживании свойства элемент "newUserProfile" был успешно установлен в codebehind.

XAML

<UserControl x:Class="CH_App.ucUserEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                          xmlns:my="clr-namespace:CH_App"

    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBox Text="{Binding Path=Email}"/>
        <my:ucDbRow Title="Email" Value="{Binding Path=Email, Mode=TwoWay}" />
    </Grid>
</UserControl>

Texbox с привязкой электронной почты работает так, как должен, и показывает адрес электронной почты. Пользовательский контроль не показывает адрес электронной почты. Пользовательский элемент управления показывает правильный заголовок.

UserControl

<UserControl x:Class="CH_App.ucDbRow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:my="clr-namespace:CH_App"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
            DataContext="{Binding RelativeSource={RelativeSource Self}}"
    d:DesignHeight="300" d:DesignWidth="400">

    <StackPanel>
        <TextBlock x:Name="txtTitle" Text="{Binding Path=Title}" />
        <TextBox x:Name="txtValue" Text="{Binding Path=Value, Mode=TwoWay}"/>
    </StackPanel>
</UserControl>

Код за контролем пользователя

#Region "Title"

    ''' <summary>
    ''' Title Dependency Property
    ''' </summary>
    Public Shared ReadOnly TitleProperty As DependencyProperty = _
        DependencyProperty.Register("Title", GetType(String), GetType(ucDbRow), _
            New Windows.PropertyMetadata(""))

    ''' <summary>
    ''' Gets or sets the Title property.  This dependency property 
    ''' indicates ....
    ''' </summary>
    Public Property Title() As String
        Get
            Return CType(GetValue(TitleProperty), String)
        End Get
        Set(ByVal value As String)
            SetValue(TitleProperty, value)
        End Set
    End Property

#End Region



#Region "Value"

    ''' <summary>
    ''' Value Dependency Property
    ''' </summary>
    Public Shared ReadOnly ValueProperty As DependencyProperty = _
        DependencyProperty.Register("Value", GetType(String), GetType(ucDbRow), _
            New Windows.PropertyMetadata(""))

    ''' <summary>
    ''' Gets or sets the Value property.  This dependency property 
    ''' indicates ....
    ''' </summary>
    Public Property Value() As String
        Get
            Return CType(GetValue(ValueProperty), Object)
        End Get
        Set(ByVal value As String)
            SetValue(ValueProperty, value)
        End Set
    End Property

#End Region

1 Ответ

2 голосов
/ 17 марта 2012

Редактировать (вставить):

Вы используете Silverlight 4, и я либо проводил тестирование в Silverlight 5, либо в WPF, из которых, вероятно, оба, но
WPF, безусловно, поддерживает RelativeSourceBinding таким образом, однако вы сделали это почти правильно.
Вывод окно в Visual Studio выдает следующую ошибку, если я прав.

Ошибка System.Windows.Data: ошибка пути BindingExpression:
Свойство «Email» не найдено в «VisualBasicSilverlightApplication1.ucDbRow»
'VisualBasicSilverlightApplication1.ucDbRow' (HashCode = 72766).
BindingExpression: Path = 'DataContext.Email'
DataItem = 'VisualBasicSilverlightApplication1.ucDbRow' (HashCode = 72766);
Целевым элементом является VisualBasicSilverlightApplication1.ucDbRow (Name = ');
Целевым свойством является 'Значение' (тип 'System.String') ..

DataContext будет проходить через usercontrol, за исключением верхнего уровня / экземпляра usercontrol.
Поэтому вместо этого:

<my:ucDbRow Title="Email" Value="{Binding Path=Email, Mode=TwoWay}" />

Единственное, что вам нужно будет изменить в своем коде, это указать на элемент, на котором вы устанавливаете DataContext, который в большинстве случаев является LayoutRoot:
(в ucUserEditor)

<my:ucDbRow Title="Email" Value="{Binding ElementName=LayoutRoot, 
            Path=DataContext.Email, Mode=TwoWay}" />

Предыдущий ответ
Вы переопределяете связанный текстовый текст с этим DataContext="{Binding RelativeSource={RelativeSource Self}}" в CH_App.ucDbRow. Удалите его, и значение сработает, потому что вы вернули подложку DataContext, однако название больше не работает.

Есть решение:

Измените ucDbRow на это:

<UserControl x:Class="CH_App.ucDbRow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding}">
    <StackPanel>
      <TextBlock x:Name="txtTitle" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Title}" Height="23"/>
      <TextBox x:Name="txtValue" Text="{Binding Path=Value, Mode=TwoWay}"/>
    </StackPanel>
  </Grid>
</UserControl>

Примечание. Проверьте окно вывода, если привязки не работают, если произошел сбой, он находится в окне вывода.

Дополнительно:

Я бы предложил , а не использовать usercontrol в качестве элементов управления. По моему мнению, пользовательские элементы управления должны больше использоваться для представления отдельного контекста, а не половины контекста в одном и половины контекста в другом. Начните смотреть на пользовательские элементы управления больше как страницы и использовать пользовательские элементы управления и таблицы данных для подробной работы. Кроме того, создание лучшего макета становится очень простым с использованием Grid, который (опять же, на мой взгляд) является одной из лучших функций в WPF и Silverlight, и его нельзя побить заказным пользовательским контролем.

...