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

Как я могу привязать элемент управления в ресурсе usercontrol к свойству? В качестве альтернативы, можно ли найти элемент управления из кода позади и получить и установить значение оттуда?

Вот моя разметка. Я разделил его только на соответствующую часть:

Salesmen.xaml:

<UserControl.Resources>
            <ControlTemplate x:Key="EditAppointmentTemplate1" TargetType="local:SchedulerDialog" x:Name="ControlTemplate">
                <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
                    <Grid>
                        <Grid Name="grdTotal" Grid.Row="4" Visibility="{Binding ResourceTypesVisibility}">
                            <TextBox x:Name="totalSalesmen" Grid.Row="0" Grid.Column="1" Margin="3" Width="120" Text="{Binding Parent.totalSalesmen, ElementName=LayoutRoot, Mode=TwoWay}" />
                        </Grid>
                </ScrollViewer>
            </ControlTemplate>
    <Style x:Key="EditAppointmentDialogStyle1" TargetType="local:SchedulerDialog">
        <Setter Property="Template" Value="{StaticResource EditAppointmentTemplate1}" />
    </Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Left" Margin="10,10,0,0">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <StackPanel Orientation="Vertical">
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" BorderBrush="Transparent">
            <telerik:RadCalendar Name="RadCalendar" SelectedDate="{Binding CurrentDate, ElementName=RadScheduleViewTests, Mode=TwoWay}" IsTodayHighlighted="True"
                         telerik:StyleManager.Theme="Metro" HorizontalAlignment="Left" VerticalAlignment="Top" FirstDayOfWeek="Sunday" Margin="0,0,15,0"
                         SelectionChanged="RadCalendar_SelectionChanged_1"  >
            </telerik:RadCalendar>
        </ScrollViewer>
    </StackPanel>

    <telerik:RadScheduleView Name="RadScheduleViewTests"  MinAppointmentWidth="100" Tag="{Binding Path=Context, ElementName=TestDayPage}"
                             telerik:StyleManager.Theme="Metro" Grid.Column="1" EditAppointmentDialogStyle="{StaticResource EditAppointmentDialogStyle1}"
                             AppointmentCreating="RadScheduleViewTests_AppointmentCreating_1" AppointmentEditing="RadScheduleViewTests_AppointmentEditing_1"
                             AppointmentDeleting="RadScheduleViewTests_AppointmentDeleting_1" FirstDayOfWeek="Sunday" ShowDialog="RadScheduleViewTests_ShowDialog_1"
                             AppointmentEdited="RadScheduleViewTests_AppointmentEdited_1">
        <telerik:RadScheduleView.DragDropBehavior>
            <examiners:CustomDragDropBehaviour/>
        </telerik:RadScheduleView.DragDropBehavior>
        <telerik:RadScheduleView.SchedulerDialogHostFactory>
            <test:CustomScheduleViewDialogHostFactory />
        </telerik:RadScheduleView.SchedulerDialogHostFactory>
        <telerik:RadScheduleView.ViewDefinitions>
            <telerik:DayViewDefinition/>
            <telerik:WeekViewDefinition/>
            <telerik:MonthViewDefinition/>
            <telerik:TimelineViewDefinition/>
        </telerik:RadScheduleView.ViewDefinitions>
    </telerik:RadScheduleView>
</Grid>

И вот моя собственность. Несмотря на двустороннюю привязку, она всегда имеет значение null:

Salesmen.xaml.cs:

string totalSalesmen { get; set; }

Я слышал о VisualTreeHelper и LogicalTreeHelper. Они могут позволить другой подход - найти контроль и получить и их вручную. Однако VisualTreeHelper видит только LayoutRoot и его дочерние элементы (а не UserControl.Resources), а LogicalTreeHelper не представляется доступным (это проект SilverLight 5, я не знаю, какая инфраструктура используется Silverlight 5. Я понимаю, что LogicalTreeHelper доступно только в версии 4.5 и более поздних)

Благодарим вас за помощь. Примечание: этот вопрос получит +50 баунти. Система требует, чтобы я подождал 2 дня, чтобы поставить щедрость, поэтому я поставлю щедрость и приму ответ через 2 дня. Я дам вам знать, будет ли ваш ответ работать до этого.

Ответ 1

Ваш Binding to totalSalesmen и все внутри EditAppointmentTemplate1 не будут иметь никакого эффекта, если Template никогда не создается. Подумайте о Template (как ControlTemplate, так и DataTemplate) в качестве плана. Элементы, которые определены внутри, создаются только тогда, когда шаблон используется где-то.

Есть ли у вас какое-то использование? например:

<Grid>
    ...
    <SchedulerDialog Template="{StaticResource EditAppointmentTemplate1}"/>
    ...
</Grid>

[Редактировать # 1]

Хорошо, посмотрим... твой twoway Binding to totalSalesmen выглядит нормально, хотя и немного вонючий. Я думаю, что свойство totalSalesmen должно скорее жить в DataContext (и с ним было бы легче связать). Но сначала попробуйте сделать ваш код работать, возможно, мы сделаем это красиво позже:

Проблема

Когда (в одном файле xaml) используется ElementName в Bindings, в то же время используя шаблоны для определения частей пользовательского интерфейса (и помните: материал в шаблонах создается только тогда, когда он используется где-то, и создание может произойти в другой момент времени) существует риск того, что элементы, которые вы ожидаете узнать друг от друга, фактически созданы в разных NameScopes. И ваши затронутые ElementName-Bindings не будут работать. Просто тихо работать не будет.

Лечение

Вы можете попробовать трюк: убедитесь, что у вас есть StaticResource, который содержит ссылку на элемент, который вы первоначально хотели использовать, ElementName. И тогда вы просто пишете Binding против этого StaticResource. Посмотрите, что я здесь сделал:

<UserControl x:Class="Salesmen" ... x:Name="me">
  <UserControl.Resources>
    <BindableObjectReference x:Key="MyUserControl" Object="{Binding ElementName=me}"/>
    <ControlTemplate x:Key="EditAppointmentTemplate1"
        TargetType="local:SchedulerDialog">
        ...
        <TextBox Text="{Binding Path=Object.totalSalesmen,
            Source={StaticResource MyUserControl}, Mode=TwoWay}"/>
        ...
    </ControlTemplate>
  </UserControl.Resources>

и код

public class BindableObjectReference : DependencyObject
{
    public object Object
    {
        get { return GetValue( ObjectProperty ); }
        set { SetValue( ObjectProperty, value ); }
    }

    public static readonly DependencyProperty ObjectProperty =
        DependencyProperty.Register( "Object", typeof( object ),
        typeof( BindableObjectReference ), new PropertyMetadata( null ) );
}

[Изменить # 2]

Когда вы привязываетесь к свойству DataContext, вы просто указываете путь, но не источник (неявно источником будет DataContext):

Text="{Binding Path=totalSalesmen, Mode=TwoWay}"

Ответ 2

Если вы добавите TotalSalesmen в DataContext шаблона, например

public class SpecialAppointment: Appointment
{
  private int _totalSalesmen = 0;
  public int TotalSalesmen 
  {get {return _totalSalesmen; }
  {set {_totalSalesmen = value; OnPropertyChanged(()=> this.TotalSalesmen);}
}

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

<TextBox Text="{Binding TotalSalesmen, Mode=TwoWay}" />

Обратите внимание, что привязка чувствительна к регистру и должна соответствовать имени свойства TotalSalesmen, а не поле _totalSalesmen.