如何绑定或以其他方式获得&设置资源中控件的值?

时间:2015-05-11 08:59:54

标签: c# silverlight telerik

如何将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>

这是我的财产。尽管双向绑定,它总是为空:

  

Salesmen.xaml.cs:

string totalSalesmen { get; set; }

我听说过VisualTreeHelperLogicalTreeHelper。这些可能会启用另一种方法 - 找到控件并手动获取它们。但是,VisualTreeHelper只看到LayoutRoot和它的子(而不是UserControl.Resources),而LogicalTreeHelper似乎不可用(它是一个SilverLight 5项目;我不知道Silverlight 5使用了什么框架。我理解LogicalTreeHelper是仅适用于4.5及更高版本)

谢谢你的帮助。 注意:此问题将获得+50赏金。系统要求我等待2天才能获得赏金,所以我会在2天后拿出赏金并接受答案。如果你的答案在此之前有效,我会通知你。

2 个答案:

答案 0 :(得分:13)

只要Binding从未实例化,您的Template totalSalesmen 以及 EditAppointmentTemplate1 中的所有内容都不会产生任何影响。 将Template(ControlTemplate和DataTemplate)视为蓝图。内部定义的元素仅在模板在某处使用时才实例化。

你在某个地方有用吗?像这样:

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

[编辑#1]

好的,让我们看看......你的twoway Binding totalSalesmen 看起来还不错,虽然有点臭。我认为属性 totalSalesmen 应该生活在DataContext中(并且更容易绑定)。 但首先让我们尝试让你的代码工作,也许我们以后会把它变得很好:

问题

当(在一个单一的xaml文件中)使用ElementName中的Bindings同时使用模板来定义UI的部分时(并记住:模板中的内容仅在创建时创建)在某个地方使用,并且创建可能发生在不同的时间点)存在风险,您希望彼此了解的元素实际上是在不同的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}"

答案 1 :(得分:1)

如果将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字段匹配。