我正在使用具有多个用户定义的依赖属性的自定义控件。我遇到了这个问题中描述的相同问题。
我的控件正在其构造函数中设置自定义依赖项属性的默认值。当我在 a 中使用控件时DataTemplate,始终使用构造函数中设置的值,即使我尝试在 XAML 中设置它也是如此。
链接问题的答案解释了 C# 代码中设置的值具有更高的优先级,更好的方法是在依赖项属性的元数据中指定默认值。
就我而言,我无法指定默认值,因为依赖项属性没有适用于所有情况的单个默认值。默认值取决于另一个属性,因此我必须在创建控件时而不是在注册属性时查找它们。
这是一些代码来帮助说明我的问题:
public partial class MyControl : UserControl
{
public static readonly DependencyProperty MyProperty =
DependencyProperty.Register(
"MyProperty",
typeof(int),
typeof(MyControl),
new FrameworkPropertyMetadata(
int.MinValue,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback("OnMyPropertyChanged")));
public MyControl() : base()
{
InitializeComponent();
this.MyProperty = GetDefaultPropertyValue();
}
public int MyProperty
{
get { return (int)GetValue(MyProperty); }
set { SetValue(MyProperty, value); }
}
private int GetDefaultPropertyValue()
{
// look up the appropriate default based on some other criteria
return 42; …Run Code Online (Sandbox Code Playgroud) 以下内容仅创建 的一个实例MyTabView。我通过在 MyTabView.xaml.cs 的构造函数中放置断点来确认这一点。该视图显示在一个选项卡中,无论我创建多少个选项卡,我只点击该构造函数一次。
<DataTemplate DataType="{x:Type vm:MyTabViewModel}" x:Shared="false">
<vw:MyTabView />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
选项卡控制:
<TabControl
Grid.Row="1"
ItemsSource="{Binding Tabs}"
SelectedItem="{Binding SelectedTab}"
>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl>
Run Code Online (Sandbox Code Playgroud)
这会导致所有选项卡反映共享未绑定到视图模型的任何状态:如果您移动GridSplitter,则所有其他选项卡中的情况都是相同的GridSplitter,因此用户会觉得您移动了所有选项卡。这太荒谬了。
我不明白。有什么办法可以TabControl同时使用多个相同类型的项目吗?
编辑:添加x:Shared="false"到DataTemplate.
更新:
所以我找到了一些修复方法,但我不太喜欢它们。我将考虑编写一个转换器来转换ObservableCollection<Object>为ObservableCollection<TabItem>- 有点像实时更新版本
coll.Select(vm => new TabItem() { Content = vm });
Run Code Online (Sandbox Code Playgroud)
...但我们会看看它是否喜欢TabItem从 获取实例ItemsSource。我的钱说不要赌它。但我们会看到。
更新2:花了一段时间才回到这个话题。交换选项卡项目集合的花招是有效的,但SelectedItem存在问题。事实证明,还有另一种解决方案(如下)不会产生该问题,并且还避免了创建必须镜像源集合中的更改的“中间人”集合的复杂性和愚蠢性。
我正在实现一个 UserControl ,它应该显示设置列表:
public class SettingPropertyItem {
string Name { get; }
Type ValueType { get; }
object Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
基于每种类型,ValueType应使用不同的 DataTemplate。
为了促进这一点,UserControl 有以下 Control,并以 aSettingPropertyItem作为其 DataContext:
<UserControl x:Class="AVDump3Gui.Controls.Settings.SettingsView">
...
<ItemsControl Items="{Binding Properties}" Margin="16,0,0,0">
<ItemsControl.ItemTemplate>
<DataTemplate>
...
<ContentControl Content="{Binding}"/>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
</UserControl>
Run Code Online (Sandbox Code Playgroud)
然后在使用 Usercontrol 的视图中,我在其 DataTemplates 中添加了一个 DataTemplate:
<sv:SettingsView.DataTemplates>
<DataTemplate DataType="{x:Type vm:SettingPropertyItem}">
...
</DataTemplate>
</sv:SettingsView.DataTemplates>
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,一切都按预期进行。但现在我有点困惑,因为我不知道如何基于 DataContext 中的属性应用不同的 DataTemplate。
对于 WPF,DataTemplateSelector 或触发器似乎是可行的方法(忽略其他框架),但它们在 Avalonia 中似乎不存在。我也尝试过样式,但选择器似乎无法访问 DataContext 属性。
如何才能做到这一点?
我有一个UserControl我用来显示UIElements 的列表.控件包含一个单独的ItemsControl,它被ItemPanelTemplate切换为一个水平StackPanel,它被ItemsSource绑定到一个DependencyProperty暴露的UserControl和它的ItemTemplate设置UserControl.Resources.
一切都很好,除了ItemTemplate永远不会得到应用,我不明白为什么.完整的来源如下.
UserControl.xaml -
<UserControl x:Name="UC" x:FieldModifier="private" x:Class="ContentSliderControl.ContentSlider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<DataTemplate x:Key="pageTemplate">
<Border CornerRadius="10" Padding="5" Height="200" Width="200" Background="#333">
<ContentControl Content="{Binding}"/>
</Border>
</DataTemplate>
<ItemsPanelTemplate x:Key="template">
<StackPanel IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled"/>
</ItemsPanelTemplate>
</UserControl.Resources>
<ItemsControl ItemsPanel="{StaticResource template}"
ItemTemplate="{StaticResource pageTemplate}"
ItemsSource="{Binding ElementName=UC,Path=Pages}"/>
Run Code Online (Sandbox Code Playgroud)
UserControl.xaml.cs -
[ContentProperty("Pages")]
public partial class ContentSlider : UserControl
{
public List<UIElement> Pages
{
get { return (List<UIElement>)GetValue(PagesProperty); …Run Code Online (Sandbox Code Playgroud) 我正在使用DataTemplates在ItemsControl中呈现项目。我想显示每个项目的工具提示。如果我使用诸如ToolTip =“ {Binding MyToolTip,Mode = OneWay}”之类的绑定,则WPF会在开始时获取一次工具提示,并且在打开时不会更新工具提示。
我的项目实现了INotifyPropertyChanged,因此原则上我可以为MyToolTip生成更改通知。问题是,工具提示是基于基础模型中的许多信息生成的。这些信息经常更改,并且为MyToolTip属性生成更改通知既麻烦又效率低下。此外,我不希望最初产生所有项目的工具提示。相反,我想强制在打开工具提示时生成一个新的工具提示。我该怎么做?
我已经看到了一个非常类似的问题的解决方案,但它没有转化为我的.(即,这篇文章:http://blogs.msdn.com/wpfsdk/archive/2007/04/16/how-do-i-programmatically-interact-with-template-generated-elements-part-ii.aspx)
我的ItemsControl绑定到一个可观察的集合,可以动态添加项目.
当我将项目添加到observable集合时,模板化项目在我的itemscontrol中正确呈现,但我无法弄清楚如何访问它.我的可观察集合改变了代码,我正在尝试访问有关的信息.我正在使用自定义DataTemplateSelector根据集合中项目的数据返回3个不同的dataTemplates之一.
这是我的ItemsControl XAML的概述:
<ItemsControl Name="myItemsControl" ItemTemplateSelector="{StaticResource myTempSelector}">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ItemsPresenter/>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
我见过的解决方案建议使用 ItemContainerGenerator.ContainerFromItem(xxx)
在这个例子中,他们总是在寻找有关ListBox或ComboBox(从ContentControl继承)的信息.但是,当我调用(在我的代码后面)时myItemsControl.ItemContainerGenerator.ContainerFromItem(xxx),我会收到一个ContentPresenter,而不是我期望的ContentControl.
然后,当我尝试访问此ContentPresenter的ContentTemplate时,我得到一个null对象异常.
我有一种预感,其余的麻烦从那里下来.
我想要做的就是从我新创建的控件中的datatemplate中找到一个文本框,并给它重点.
救命!:-)
我正在使用WPF和.NET 3.0.
我有一个相对简单的DataTemplate定义为GridView的CellTemplate.我希望DataTemplate的VisualTree属性包含FrameworkElementFactory,但当我尝试从GridViewColumnHeader.Click事件访问它时,该属性为null.为什么VisualTree为null?我需要访问它.这是ListView定义:
<ListView ItemsSource="{Binding Stuff}" GridViewColumnHeader.Click="Header_Click">
<ListView.View>
<GridView>
<GridViewColumn Width="28">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Name="statusImage" Width="16" Height="16" Source="../Images/media_play_green_16x16.png"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Run Code Online (Sandbox Code Playgroud)
这是事件处理程序:
private void Header_Click(object sender, RoutedEventArgs e)
{
GridViewColumnHeader gvch = e.OriginalSource as GridViewColumnHeader;
// error! VisualTree is null!
//gvch.Column.CellTemplate.VisualTree.GetType();
}
Run Code Online (Sandbox Code Playgroud) DataTemplate还有另一个令人头痛的问题.
描述:
使用Silverlight 4,Mvvm等(用于Silverlight LOB应用程序的标准开发工具集).
实体列表成功绑定到DataGrid.一个属性(可空的bool BoolValue)负责实体行为,并在datagrid中显示图片,点击这将导致更改LayoutRoot元素中某些控件的可见性.
问题:
问题在于,不幸或幸运的是,ElementName绑定内部DataTemplate没有看到除此之外的其他元素,这些元素放在此模板中.
代码示例:
<navigation:DataGridTemplateColumn Width="40"
CanUserReorder="True"
CanUserSort="False">
<navigation:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border Background="GhostWhite">
<Grid>
<Image x:Name="ImageWithTrigger"
Grid.Column="1"
Margin="10,4,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Cursor="Hand"
Source="images/someImage.png"
Stretch="None"
Visibility={Binding BoolValue, Converter={StaticResource boolToVisibilityConverter} }>
<i.Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<AttachedBehaviors:TrickyBehavior FrameworkElementToHide="{Binding ElementName=FirstControlOutside}"
FrameworkElementToShow="{Binding ElementName=SecoundControlOutside}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
</Border>
</DataTemplate>
</navigation:DataGridTemplateColumn.CellTemplate>
</navigation:DataGridTemplateColumn>
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,FrameworkElementToHide和FrameworkElementToShow始终为null.
互联网上有很多非常类似的问题和解决方案,但我没有找到解决这个问题的任何简单而优雅的方法.
问题:
有没有办法DataTemplate在XAML中定义一个并在代码中实例化它(而不是检索单例FindResource)并VisualTree在发送到DataTemplate需要的地方之前修改它,例如DataGridTemplateColumn.CellTemplate?
背景:
我通过自己添加列来显示一个二维数组data[][],并且在XAML中定义了一个知道如何呈现数组中每个元素的数组.但是,每个单元格的默认值是行,即.所以,我需要"参数"的由根视觉元素的设置为每列有约束力的地方是列索引.目前,每次都定义为返回同一实例并在其中检索.除了电话给我的树,而不是加载的本身.我正在寻找一种方法来实例化代码,进行所需的修改并设置为.DataGridDataGridTemplateColumnDataTemplateDataContextdata[x]DataTemplateDataContext"[y]"yDataTemplateDataGrid.ResourcesFindResource()LoadContent()UIElementVisualTreeDataTemplateDataTemplateDataGridTemplateColumn.CellTemplate
我搜索某种方式来显示ItemsControl正在使用的项目索引DataTemplate.所以我发现了这个好问题.我在那个问题中使用了这个想法,但所有的值都是零!我的代码和该问题中的代码之间唯一不同的是我的控件(即将显示索引)不是直接在DataTemplate.它在a Grid和Gridin中DataTemplate
这是我的代码:
<ItemsControl ItemsSource="{Binding }">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
// column definitions
<Label Content="{Binding RelativeSource={RelativeSource
Mode=TemplatedParent},
Path=(ItemsControl.AlternationIndex)}"/>
// some other controls
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
结果:
0
0
0
// and so on
Run Code Online (Sandbox Code Playgroud)
我希望展示的内容:
0
1
2
// and so on
Run Code Online (Sandbox Code Playgroud)
这段代码有什么问题?
datatemplate ×10
wpf ×8
c# ×4
itemscontrol ×3
xaml ×3
.net ×1
avaloniaui ×1
binding ×1
celltemplate ×1
datagrid ×1
itemspanel ×1
itemtemplate ×1
silverlight ×1
tabcontrol ×1
tooltip ×1
visual-tree ×1