Win*_*don 6 c# wpf listbox datatemplate mvvm
我有一个ListBox它ItemTemplate看起来像这样:
<DataTemplate DataType="local:Column">
<utils:EditableTextBlock x:Name="editableTextBlock" Text="{Binding Name, Mode=TwoWay}"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
Column 是一个简单的类,看起来像这样:
public Column(string name, bool isVisibleInTable)
{
Name = name;
IsVisibleInTable = isVisibleInTable;
}
public string Name { get; set; }
public bool IsVisibleInTable { get; set; }
Run Code Online (Sandbox Code Playgroud)
该EditableTextBlock是UserControl说变成了TextBox双次点击时回百转成TextBlock失落时对焦.它还有一个被称为属性的属性IsInEditMode,默认为false.如果是,TextBox则显示.
问题:
在ItemsSouceListBox的是ObservableCollection<Column>.我有一个按钮,Column可以为集合添加新的内容.但我的问题是,我希望通过该ButtonIsInEditMode为新添加的EditableTextBlocks 变为真.但我只能在ViewModel中访问.我如何访问集合中指定的? ColumnEditableTextBlockColumnItemsSource
我能想出的唯一解决方案是从中派生一个类Column并为其添加一个属性(例如:name:IsInEditMode)(或者也许是一个包装类.这里是一个类似的答案,建议使用包装类)并绑定到该属性DataTemplate如下:
<DataTemplate DataType="local:DerivedColumn">
<utils:EditableTextBlock x:Name="editableTextBlock" Text="{Binding Name, Mode=TwoWay}"
IsInEditMode="{Binding IsInEditMode}"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
但我不想要这个.我想要一些方法在XAML中执行此操作,而无需派生类和添加不必要的代码.(并且还遵守MVVM规则)
如果您有能力向用户控件添加新的依赖属性,EditableTextBlock您可以考虑添加一个名为 的依赖属性StartupInEditMode,默认为false来保留现有行为。
Loaded然后,的处理程序可以确定UserControl的状态,StartupInEditMode以决定如何初始设置 的值IsInEditMode。
//..... Added to EditableTextBlock user control
public bool StartupInEdit
{
get { return (bool)GetValue(StartupInEditProperty); }
set { SetValue(StartupInEditProperty, value); }
}
public static readonly DependencyProperty StartupInEditProperty =
DependencyProperty.Register("StartupInEdit", typeof(bool), typeof(EditableTextBlock ), new PropertyMetadata(false));
private void EditableTextBlock_OnLoaded(object sender, RoutedEventArgs e)
{
IsInEditMode = StartupInEditMode;
}
Run Code Online (Sandbox Code Playgroud)
对于视觉树中已有的控件,更改值StartupInEdit并不重要,因为它仅在创建时评估一次。ListBox这意味着您可以填充每个EditableTextBlock不处于编辑模式的集合,然后在开始添加新项目时切换StartupInEditmMode模式。True然后每个新EditableTextBlock控件都会以编辑模式启动。
您可以通过指定此新属性指向视图变量而不是集合项的DataTemplate位置来完成此行为切换。Binding
<DataTemplate DataType="local:Column">
<utils:EditableTextBlock x:Name="editableTextBlock"
Text="{Binding Name, Mode=TwoWay}"
StartupInEditMode="{Binding ANewViewProperty, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
Window您需要向本示例中调用的父级(或Page用作视图容器的任何内容)添加一个属性ANewViewProperty。如果您将绑定更改为 ,则该值可能是视图模型的一部分{Binding DataContext.ANewViewProperty, RelativeSource={RelativeSource AncestorType={x:Type Window}}}。
这个新属性 ( ANewViewProperty) 甚至不需要实现INotifyPropertyChanged,因为绑定将在创建新EditableTextBlock控件时获取初始值,并且如果该值稍后发生更改,则无论如何都不会产生影响。
您可以在最初加载时设置ANewViewPropertyto的值。当您按下按钮将新项目添加到列表中时,将 的值设置为 ,表示现在将在编辑模式下启动创建的控件。FalseListBox ItemSourceANewViewPropertyTrue
仅代码、仅查看的替代方案(类似于 user2946329 的答案)是挂钩到ListBox.ItemContainerGenerator.ItemsChanged添加新项目时将触发的处理程序。一旦触发,您现在就可以对新项目进行操作(通过 Boolean ),它会为新添加的项目找到适当视觉容器的DetectingNewItems第一个后代控件。一旦获得了控件的引用,就可以更改属性。EditableTextBlockListBoxItemIsInEditMode
//.... View/Window Class
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
MyListBox.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
}
private void ItemContainerGenerator_ItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e)
{
if ((e.Action == NotifyCollectionChangedAction.Add) && DetectingNewItems)
{
var listboxitem = LB.ItemContainerGenerator.ContainerFromIndex(e.Position.Index + 1) as ListBoxItem;
var editControl = FindFirstDescendantChildOf<EditableTextBlock>(listboxitem);
if (editcontrol != null) editcontrol.IsInEditMode = true;
}
}
public static T FindFirstDescendantChildOf<T>(DependencyObject dpObj) where T : DependencyObject
{
if (dpObj == null) return null;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dpObj); i++)
{
var child = VisualTreeHelper.GetChild(dpObj, i);
if (child is T) return (T)child;
var obj = FindFirstChildOf<T>(child);
if (obj != null) return obj;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
向视图添加一个属性,该属性引用回 ViewModel 假设您在以下位置保留对视图模型的引用DataContext:-
..... // Add this to the Window/Page
public bool DetectingNewItems
{
get
{
var vm = DataContext as MyViewModel;
if (vm != null)
return vm.MyPropertyOnVM;
return false;
}
}
.....
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
371 次 |
| 最近记录: |