Windows Presentation Foundation或WPF是用于在基于Windows的应用程序中呈现用户界面的子系统。
我有一个通用的WPF窗口,它使用MVVM模式。因此,一旦声明,它就会收到一个 ViewModel 对象。此窗口的目的是在
我基于 DataGrid 构建了一个 UserControl,以便添加我没有详细说明的过滤功能。它相当复杂,但效果很好(稍后我必须弄清楚如何删除大量隐藏代码)。 我...
我是 C# 和 WPF 的新手,老实说这周才开始自学。我正在尝试制作一个突出显示红色的下拉菜单(表示此字段是必需的),直到选择一个项目...
如何从HierarchicalDataTemplate项目中获取TreeViewItem?
我有一个 TreeView,它使用 HierarchicalDataTemplate 来绑定其数据。 它看起来像这样: 我有一个 TreeView,它使用 HierarchicalDataTemplate 来绑定其数据。 看起来像这样: <TreeView x:Name="mainTreeList" ItemsSource="{Binding MyCollection}> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type local:MyTreeViewItemViewModel}" ItemsSource="{Binding Children}"> <!-- code code code --> </HierarchicalDataTemplate> </TreeView.Resources> </TreeView> 现在,从主窗口的代码隐藏中,我想获取当前选定的TreeViewItem。但是,如果我使用: this.mainTreeList.SelectedItem; selectedItem 的类型为 MyTreeViewItemViewModel。但我想得到“父母”或“绑定”TreeViewItem。我不会将其传递给我的 TreeViewItemModel 对象(甚至不知道如何传递)。 我该怎么做? TreeViewItem item = (TreeViewItem)(mainTreeList .ItemContainerGenerator .ContainerFromIndex(mainTreeList.Items.CurrentPosition)); 不起作用(对我来说),因为使用 HierarchicalDataTemplate 的树视图中的 mainTreeList.Items.CurrentPosition 将始终为 -1。 也没有,因为使用 HierarchicalDataTemplate 的树视图中的 mainTreeList.Items.CurrentItem 将始终为 null。 TreeViewItem item = (TreeViewItem)mainTreeList .ItemContainerGenerator .ContainerFromItem(mainTreeList.Items.CurrentItem); INSTEAD 我必须在路由的 TreeViewItem.Selected 事件中设置最后选定的 TreeViewItem,该事件会冒泡到树视图(TreeViewItem 本身在设计时不存在,因为我们使用的是 HierarchicalDataTemplate)。 可以在 XAML 中捕获事件,如下所示: <TreeView TreeViewItem.Selected="TreeViewItemSelected" .../> 然后可以在事件中设置最后选择的 TreeViewItem,如下所示: private void TreeViewItemSelected(object sender, RoutedEventArgs e) { TreeViewItem tvi = e.OriginalSource as TreeViewItem; // set the last tree view item selected variable which may be used elsewhere as there is no other way I have found to obtain the TreeViewItem container (may be null) this.lastSelectedTreeViewItem = tvi; ... } 来自 Bea Stollnitz 关于此的博客条目,请尝试 TreeViewItem item = (TreeViewItem)(mainTreeList .ItemContainerGenerator .ContainerFromIndex(mainTreeList.Items.CurrentPosition)); 我遇到了同样的问题。 我需要访问 TreeViewItem 以便选择它。 然后我意识到我可以将属性 IsSelected 添加到我的 ViewModel,然后将其绑定到 TreeViewItems IsSelectedProperty。 这可以通过 ItemContainerStyle 来实现: <TreeView> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> </Style> </TreeView.ItemContainerStyle> </TreeView> 现在,如果我想选择树视图中的某个项目,我只需直接在 ViewModel 类上调用 IsSelected 即可。 希望它对某人有帮助。 TreeViewItem item = (TreeViewItem)(mainTreeList .ItemContainerGenerator .ContainerFromIndex(mainTreeList.Items.CurrentPosition)); gives first item in the TreeView because CurrentPosition is always 0. 怎么样 TreeViewItem item = (TreeViewItem)(mainTreeList .ItemContainerGenerator .ContainerFromItem(mainTreeList.SelectedItem))); 这对我来说效果更好。 受 Fëanor 答案的启发,我尝试让已创建 TreeViewItem 的每个数据项都可以轻松访问 TreeViewItem。 这个想法是向视图模型添加一个 TreeViewItem 类型的字段,也通过接口公开,并且每当创建 TreeView 容器时让 TreeViewItem 自动填充它。 这是通过子类化 TreeView 并将事件附加到 ItemContainerGenerator 来完成的,每当创建 TreeViewItem 时都会记录它。问题包括 TreeViewItem 是懒惰创建的,因此在某些时间可能真的没有可用的。 自从发布这个答案以来,我进一步开发了它并在一个项目中使用了很长时间。到目前为止没有任何问题,除了这违反了 MVVM(但也为您节省了大量简单案例的样板文件)。来源这里。 用法 选择所选项目的父项并将其折叠,确保它位于视图中: ... var selected = myTreeView.SelectedItem as MyItem; selected.Parent.TreeViewItem.IsSelected = true; selected.Parent.TreeViewItem.IsExpanded = false; selected.Parent.TreeViewItem.BringIntoView(); ... 声明: <Window ... xmlns:tvi="clr-namespace:TreeViewItems" ...> ... <tvi:TreeViewWithItem x:Name="myTreeView"> <HierarchicalDataTemplate DataType = "{x:Type src:MyItem}" ItemsSource = "{Binding Children}"> <TextBlock Text="{Binding Path=Name}"/> </HierarchicalDataTemplate> </tvi:TreeViewWithItem> ... </Window> class MyItem : IHasTreeViewItem { public string Name { get; set; } public ObservableCollection<MyItem> Children { get; set; } public MyItem Parent; public TreeViewItem TreeViewItem { get; set; } ... } 代码 public class TreeViewWithItem : TreeView { public TreeViewWithItem() { ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged; } private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) { var generator = sender as ItemContainerGenerator; if (generator.Status == GeneratorStatus.ContainersGenerated) { int i = 0; while (true) { var container = generator.ContainerFromIndex(i); if (container == null) break; var tvi = container as TreeViewItem; if (tvi != null) tvi.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged; var item = generator.ItemFromContainer(container) as IHasTreeViewItem; if (item != null) item.TreeViewItem = tvi; i++; } } } } interface IHasTreeViewItem { TreeViewItem TreeViewItem { get; set; } } 尝试这样的事情: public bool UpdateSelectedTreeViewItem(PropertyNode dateItem, ItemsControl itemsControl) { if (itemsControl == null || itemsControl.Items == null || itemsControl.Items.Count == 0) { return false; } foreach (var item in itemsControl.Items.Cast<PropertyNode>()) { var treeViewItem = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; if (treeViewItem == null) { continue; } if (item == dateItem) { treeViewItem.IsSelected = true; return true; } if (treeViewItem.Items.Count > 0 && UpdateSelectedTreeViewItem(dateItem, treeViewItem)) { return true; } } return false; } 我将 William 的递归搜索修改为更紧凑的版本: public TreeViewItem GetTreeViewItemFromObject(ItemContainerGenerator container, object targetObject) { if (container.ContainerFromItem(targetObject) is TreeViewItem target) return target; for (int i = 0; i < container.Items.Count; i++) if ((container.ContainerFromIndex(i) as TreeViewItem)?.ItemContainerGenerator is ItemContainerGenerator childContainer) if (GetTreeViewItemFromObject(childContainer, targetObject) is TreeViewItem childTarget) return childTarget; return null; } 可以通过提供 TreeView 实例的 ItemContainerGenerator 和目标数据对象来调用它: TreeViewItem tvi = GetTreeViewItemFromObject(treeView.ItemContainerGenerator, targetDataObject); 单个 ItemContainerGenerator.ContainerFromItem 或 ItemContainerGenerator.ItemContainerGenerator 调用无法找到与树视图对象关联的 TreeViewItem,因为树视图项控制器和树视图项数据是分离的。 需要创建一个递归函数来使用 ItemContainerGenerator.ContainerFromItem 和 ItemContainerGenerator.ItemContainerGenerator,以便在树视图中定位 TreeViewItem。 示例递归函数可能如下所示: private TreeViewItem GetTreeViewItemFromObject(ItemContainerGenerator container, object tvio) { var item = container.ContainerFromItem(tvio) as TreeViewItem; if (item != null) { return item; } for (int i = 0; i < container.Items.Count; i++) { var subContainer = (TreeViewItem)container.ContainerFromIndex(i); if (subContainer != null) { item = GetTreeViewItemFromObject(subContainer.ItemContainerGenerator, tvio); if (item != null) { return item; } } } return null; } 呼叫者 var target = GetTreeViewItemFromObject(treeView.ItemContainerGenerator, item); 递归函数仅在树视图的 ItemContainerGenerator.Status 为 ContainersGenerated 后才起作用。所以在初始化视图期间,GetTreeViewItemFromObject不起作用。 您是否需要 TreeViewItem 因为您要修改正在显示的内容?如果是这种情况,我建议使用 Style 来更改项目的显示方式,而不是使用代码隐藏,而不是直接修改 TreeViewItem。希望它会更干净。 如果您必须在孩子的孩子中查找项目,您可能必须使用像这样的递归 public bool Select(TreeViewItem item, object select) // recursive function to set item selection in treeview { if (item == null) return false; TreeViewItem child = item.ItemContainerGenerator.ContainerFromItem(select) as TreeViewItem; if (child != null) { child.IsSelected = true; return true; } foreach (object c in item.Items) { bool result = Select(item.ItemContainerGenerator.ContainerFromItem(c) as TreeViewItem, select); if (result == true) return true; } return false; } 这是解决方案。 rtvEsa 是树视图。 HierarchicalDataTemplate 是树视图模板 标签使当前项目真正消耗。这不是选定的项目,它是使用 HierarchicalDataTemplate 的树控件中的当前项目。 Items.CurrentItem 是内部树集合的一部分。 您无法获得许多不同的数据。例如 Items.ParenItem 也是如此。 <HierarchicalDataTemplate ItemsSource="{Binding ChildItems}"> <TextBox Tag="{Binding ElementName=rtvEsa, Path=Items.CurrentItem }" /> 我的 TreeView 模板只有一级标题,所以我发现成功了: foreach (CollectionViewGroup grp in treeView.Items) { string strHeader = (string)grp.Name; TreeViewItem treeViewItem = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(grp);
WPF - 无法删除 DataGrid 单元格周围的填充/边距
我尝试修改数据网格单元周围的白色边距 (我隐藏了单元格的 H/V 标题,也很抱歉隐藏单元格中的文本,这是公司财产相关的东西) 这是我如何定义
我想制作一个自定义 GridSplitter,它结合了常规拆分器行为和一个功能 - 当拆分器自动将其中一个区域的大小调整为零时。 所以正常的用法是: ...
我正在查看 WPF 工具包中的 Accordion Control 示例: http://www.dotnetspark.com/kb/1931-accordion-wpf-toolkit-tutorial.aspx 我把我用来调整赌注大小的两个项目放在那里......
WPF/C# TabItem 水平手风琴样式的标题。可能吗?
我有一个TabControl,我想更改标题样式。 我使用 C# 和 WPF。 TabItem 标题需要采用水平手风琴样式。 我希望你明白我的意思。如果你没有...
我正在尝试实现一个 DataGrid,其中一列有一个复杂的对象,而组合框(网格外)有一个该列的同一时间对象的列表。使用 WPF 和 MVVM。 当我...
我正在将桌面桥用于 WPF 桌面应用程序,并希望在构建过程中自动创建 msix 包。我不想在源代码管理中存储任何版本信息...
<ListBox x:Name="myData" ItemsSource="{Binding Data}" Background="{StaticResource TransparentColor}" Grid.Row="1" BorderBrush="{StaticResource LeftGridColor}" > <ListBox.Resources> <Style TargetType="ScrollViewer" BasedOn="{StaticResource MaterialDesignScrollViewer}" /> <Style TargetType="ScrollBar" BasedOn="{StaticResource MaterialDesignScrollBarMinimal}" /> <DataTemplate DataType="{x:Type dto:DownLoadDto}"> <Grid Background="{StaticResource ThemeColor}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="10*"/> <ColumnDefinition Width="5*"/> <ColumnDefinition Width="2*"/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <Grid Grid.Column="0"> <TextBlock Text="{Binding index}" /> </Grid> <Grid Grid.Column="1"> <WrapPanel > <Image Source="{Binding Image}" Width="40"/> <StackPanel Margin="10,0,0,0"> <TextBlock Text="{Binding Name}"/> <TextBlock Text="{Binding Des}" /> </StackPanel> </WrapPanel> </Grid> <Grid Grid.Column="2"> <TextBlock Text="{Binding Album}" /> </Grid> <Grid Grid.Column="3"> <Path Data="M0,0 L100,0 L100,100 L0,100 Z " Fill="Red" Stroke="Red" Stretch="Fill" Width="16" Height="16"/> </Grid> <Grid Grid.Column="4"> <TextBlock Text="{Binding Size}"/> </Grid> </Grid> </DataTemplate> </ListBox.Resources> </ListBox> 我希望Datatemple中的内容按照我设定的比例填充,但实际上它们非常接近。这个问题让我很烦恼,我很想得到你的答案 我尝试设置 HorizontalContentAlignment = "Stretch" 结果靠得很近 这就是我所期望的: 此样式使用固定宽度,我希望样式与摆动成比例 ListBoxes 和 ListViews 是 WPF 中的一个难题。您需要更新 ListBox.ItemContainerStyle 以水平拉伸 Content Presenter。 <ListBox x:Name="myData"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <!--*** THIS GUY ***--> <ContentPresenter HorizontalAlignment="Stretch" /> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListBox.ItemContainerStyle> <ListBoxItem> <Grid HorizontalAlignment="Stretch"> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*" /> <ColumnDefinition Width="10*" /> <ColumnDefinition Width="5*" /> <ColumnDefinition Width="2*" /> <ColumnDefinition Width="2*" /> </Grid.ColumnDefinitions> <Grid Grid.Column="0"> <TextBlock Text="1" /> </Grid> <Grid Grid.Column="1"> <WrapPanel> <Rectangle Fill="LightGray" Width="40" Height="40"/> <StackPanel Margin="10,0,0,0"> <TextBlock Text="NAME" /> <TextBlock Text="DES" /> </StackPanel> </WrapPanel> </Grid> <Grid Grid.Column="2"> <TextBlock Text="ALBUM" /> </Grid> <Grid Grid.Column="3"> <Path Data="M0,0 L100,0 L100,100 L0,100 Z " Fill="Red" Stroke="Red" Stretch="Fill" Width="16" Height="16" /> </Grid> <Grid Grid.Column="4"> <TextBlock Text="SIZE" /> </Grid> </Grid> </ListBoxItem>
将XAML中Material Design中按钮样式的高度属性设置为默认
我在 XAML 框架中使用 MaterialDesign 来设计我的 WPF 应用程序。 在我的应用程序中的一个地方,我想使用一个通过 MaterialDesignPaperButton 设计样式的按钮。 因为我有点想要...
我有一个安装在 Windows 10 PC 上的 WPF C# 桌面应用程序。该应用程序供客户在前台接待处使用,在那里他们完成一组特定的任务。在最后一步...
我有一个数据网格,其中删除图标作为一列,更新图标作为另一列。单击更新后,第一个单元格将获得焦点。 单击删除时,我想删除所选行,但是...
我正在尝试在 WPF 应用程序中创建类似以下的内容:https://csacademy.com/app/graph_editor/,但我不太确定如何实现它。我想我需要创建一些类似自定义元素的东西......
我希望能够更改工具窗口的背景颜色(它是 VSIX,而不是应用程序) 所以我需要以编程方式让PanelBackground指向PanelBackgroundLight或PanelBackgrou...
我正在克隆进行编辑的项目有问题。当我克隆它并打开它时,我的所有 xaml 文件都显示一半代码、一半界面设计器。 半代码,保留设计师形象 但一旦我...
单独的 DataGrid 绑定到同一个 Observable 集合
我有一个带有 TabControl 的 WPF 应用程序,在两个不同的 TabItem 上,我想在每个 TabItem 上的 DataGrid 中显示相同的内容。 操作顺序如下: 用户选择信号或...
我在使用 MultiBinding 和我的自定义 IMulitValueConverter (使用 wpf 和 c#)时遇到问题。 首先,我将向您展示我的 ViewModel 和一些 xaml 代码,然后我将描述我的问题。 我的 ViewMod...
在编辑模式下禁用 Drop inside DataGrid 单元格
我的应用程序是一个酒瓶/酒架跟踪工具,允许用户快速查找一组酒架中特定酒瓶的位置。 我有拖放功能...