如何绑定或以其他方式获取和设置资源中控件的值?
How can I bind or otherwise get & set a value of a control in a resource?
如何将用户控件资源中的控件绑定到 属性?或者,我可以从后面的代码中找到控件并从那里获取和设置值吗?
这是我的标记。我已将其简化为相关部分:
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; }
我听说过 VisualTreeHelper and the LogicalTreeHelper。这些可能会启用另一种方法——找到控件并手动获取它们。但是,VisualTreeHelper 只能看到 LayoutRoot 及其子项(不是 UserControl.Resources),而 LogicalTreeHelper 似乎不可用(这是一个 SilverLight 5 项目;我不知道 Silverlight 5 使用什么框架。我明白了LogicalTreeHelper 仅在 4.5 及更高版本中可用)
感谢您的帮助。 注意:此问题将获得 +50 赏金。系统要求我等待2天才能放赏金,所以我会放赏金并在2天后接受答案。在那之前我会通知你你的答案是否有效。
您的 Binding
到 totalSalesmen 以及 EditAppointmentTemplate1 中的所有内容只要 Template
永远不会实例化。
将 Template
(ControlTemplate 和 DataTemplate)视为蓝图。里面定义的元素只有在某处使用模板时才会实例化。
你有什么用处吗?像这样:
<Grid>
...
<SchedulerDialog Template="{StaticResource EditAppointmentTemplate1}"/>
...
</Grid>
[编辑#1]
好吧,让我们看看...你的双向 Binding
到 totalSalesmen 看起来不错,虽然有点臭。我认为 属性 totalSalesmen 应该住在 DataContext
中(这样会更容易绑定)。
但首先让我们尝试让您的代码正常工作,也许我们稍后会做得更好:
问题
当(在一个 xaml 文件中)在 Bindings
中使用 ElementName
同时使用模板定义 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}"
如果您将 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
。
如何将用户控件资源中的控件绑定到 属性?或者,我可以从后面的代码中找到控件并从那里获取和设置值吗?
这是我的标记。我已将其简化为相关部分:
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; }
我听说过 VisualTreeHelper and the LogicalTreeHelper。这些可能会启用另一种方法——找到控件并手动获取它们。但是,VisualTreeHelper 只能看到 LayoutRoot 及其子项(不是 UserControl.Resources),而 LogicalTreeHelper 似乎不可用(这是一个 SilverLight 5 项目;我不知道 Silverlight 5 使用什么框架。我明白了LogicalTreeHelper 仅在 4.5 及更高版本中可用)
感谢您的帮助。 注意:此问题将获得 +50 赏金。系统要求我等待2天才能放赏金,所以我会放赏金并在2天后接受答案。在那之前我会通知你你的答案是否有效。
您的 Binding
到 totalSalesmen 以及 EditAppointmentTemplate1 中的所有内容只要 Template
永远不会实例化。
将 Template
(ControlTemplate 和 DataTemplate)视为蓝图。里面定义的元素只有在某处使用模板时才会实例化。
你有什么用处吗?像这样:
<Grid>
...
<SchedulerDialog Template="{StaticResource EditAppointmentTemplate1}"/>
...
</Grid>
[编辑#1]
好吧,让我们看看...你的双向 Binding
到 totalSalesmen 看起来不错,虽然有点臭。我认为 属性 totalSalesmen 应该住在 DataContext
中(这样会更容易绑定)。
但首先让我们尝试让您的代码正常工作,也许我们稍后会做得更好:
问题
当(在一个 xaml 文件中)在 Bindings
中使用 ElementName
同时使用模板定义 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}"
如果您将 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
。