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

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

Подскажите, пожалуйста, как получить переплетную работу?

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

Программный код главной страницы 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» был успешно установлен в выделенном коде.

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

<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

person Nasenbaer    schedule 16.03.2012    source источник
comment
Это вопрос WPF или Silverlight?   -  person NVM    schedule 16.03.2012
comment
Я работаю над Silverlight. Но в прошлом месяце у меня была аналогичная проблема с WPF, но я нашел обходной путь без привязки. Теперь я хочу исправить это, потому что уверен, я просто пропустил небольшой фрагмент объявления. Я пробовал несколько часов с разными ключевыми словами Binding, но это не сработало.   -  person Nasenbaer    schedule 16.03.2012
comment
Я прочитал вопрос дважды, но до сих пор не понимаю, что вы пытаетесь сделать. В первую очередь опишите, чего вы хотите достичь.   -  person NVM    schedule 16.03.2012
comment
Спасибо за совет. Обновлю вопрос по картинке.   -  person Nasenbaer    schedule 16.03.2012
comment
Н.П. Думаю, я знаю, в чем ваша проблема, но я думаю, что вы делаете то, чего не должны делать. Я думаю, что решение вашей непосредственной проблемы будет означать, что вы позволите себе зарыться в большую яму, чем вы уже находитесь.   -  person NVM    schedule 16.03.2012
comment
Привет, NVM: я думаю, что привязка очень четкая и прозрачная, и я не чувствую, что нахожусь в дыре. Но как бы просто он ни работал, он просто не делает того, что от него ожидается. Если у вас есть какой-то неправильный товар или образец, это было бы здорово. Я не люблю использовать шаблоны, я также могу поделиться своим проектом для загрузки, если вы хотите увидеть, как он работает сейчас.   -  person Nasenbaer    schedule 16.03.2012
comment
В порядке. Я обновил вопрос. Еще раз спасибо за совет. В противном случае я получил отрицательные голоса, и я не знаю почему. В этом случае ваша помощь уже была хороша.   -  person Nasenbaer    schedule 16.03.2012
comment
Почему вам не нравятся шаблоны, это очевидный путь?   -  person Phil    schedule 17.03.2012


Ответы (1)


Изменить (вставить):

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

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

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

<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, которую невозможно превзойти с помощью упорядоченных пользовательских элементов управления.

person Silvermind    schedule 16.03.2012
comment
Привет, Silvermind. Спасибо за Ваш ответ. Я с вами в отношении пользовательских элементов управления, но это расширило бы вопрос, если бы я объяснил все здесь. Я тоже делал стековую панель только для вопросов. Я новичок в использовании AncestorType, и я уже получил сообщение ERROR при вводе в Silverlight XAML ucDbRow о том, что AncestorType не был найден как относительный источник. Любой совет? - person Nasenbaer; 18.03.2012
comment
@Nasenbaer Потому что ему нужно ваше пространство имен. xmnls: local = clr-namespace: mynamespace и Ancestortype = {x: Type local: ucDbRow} - person Silvermind; 18.03.2012
comment
Кстати: если ucDbRow является UserControl (как показано в вашем примере xaml, я предполагаю, что да), то вы также можете указать слово UserControl как AncestorType. - person Silvermind; 18.03.2012
comment
Возможно, я слишком мелко думаю. Но ни одна из идей не сработала: я все еще не понимаю, где что-то изменить, чтобы избежать сообщения об ошибке синтаксического анализатора XAML при правильной привязке к контексту. Можете ли вы добавить в образец больше кода? - person Nasenbaer; 20.03.2012
comment
Вы точно скопировали предоставленный мной XAML, потому что он определенно должен работать? Если ucDbRow не является UserControl в коде, но это должно привести к большему количеству (разных) ошибок. У меня сейчас нет времени создавать полный пример. Может быть, примерно через 6 часов. - person Silvermind; 20.03.2012
comment
@Nasenbaer Я обновил свой ответ и, если хотите, опубликую весь созданный мной код, но в этом нет необходимости, поскольку на этот раз ответ должен быть правильным. :) - person Silvermind; 20.03.2012