C# 如何使用MVVM在另一个控件之间插入控件?
我想在光标所在的文本框下方插入一个控件: 我在MVVM中有此代码,文本框是动态创建的:C# 如何使用MVVM在另一个控件之间插入控件?,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我想在光标所在的文本框下方插入一个控件: 我在MVVM中有此代码,文本框是动态创建的: <ItemsControl IsTabStop="False" ItemsSource="{Binding ListControls}"> <ItemsControl.ItemTemplate> <DataTemplate> <Grid HorizontalAlignment="Stretch">
<ItemsControl IsTabStop="False" ItemsSource="{Binding ListControls}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding RGN_INdex}" Margin="5,5,5,5" FontSize="14" VerticalContentAlignment="Center"/>
<TextBox Style="{StaticResource blankColor}" Text="{Binding RGN}" Grid.Column="1" FontSize="14" VerticalContentAlignment="Center" Margin="0,5,0,5"/>
<Label Grid.Column="2" Content="RSN:" Margin="5,5,5,5" FontSize="14" VerticalContentAlignment="Center"/>
<TextBox Style="{StaticResource blankColor}" Text="{Binding RSN}" Grid.Column="3" FontSize="14" VerticalContentAlignment="Center" Margin="0,5,0,5"/>
<Label Grid.Column="4" Content="SGN:" Margin="5,5,5,5" FontSize="14" VerticalContentAlignment="Center"/>
<TextBox Style="{StaticResource blankColor}" Text="{Binding SGN}" Grid.Column="5" FontSize="14" VerticalContentAlignment="Center" Margin="0,5,0,5"/>
<Label Grid.Column="6" Content="SN:" Margin="5,5,0,5" FontSize="14" VerticalContentAlignment="Center"/>
<TextBox Style="{StaticResource blankColor}" Text="{Binding SN}" Grid.Column="7" FontSize="14" VerticalContentAlignment="Center" Margin="0,5,5,5"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
当我将光标放在文本框1
并按下按钮时,这将在列表中添加一项。然后,视图将填充另一个文本框
因此,在我看来,我将:
Textbox1
Textbox3
Textbox2
在我的XAML中,我有RGN_索引
——这将保存所创建控件的索引
在我看来,当光标聚焦在控件中时,我需要获得RGN\u索引。但是我怎么能做到呢?然后将其传递给命令,以便在找到RGN\u索引后插入列表?但是如何获取所选文本框的RGN\u索引
我是MVVM的新手,我不知道如何实现这一点。没有简单的答案,但让我来指导您如何做到这一点
让我先添加缺失的代码:
using Prism.Mvvm;
public class Ctrl
{
public int RGN_Index { get; set; }
public string RGN { get; set; }
public string RSN { get; set; }
public string SGN { get; set; }
public string SN { get; set; }
}
public class TheViewModel : BindableBase
{
public ObservableCollection<Ctrl> ListControls { get { return _listControls; } set { SetProperty(ref _listControls, value); } }
private ObservableCollection<Ctrl> _listControls;
// Constructor
public class TheViewModel()
{
ListControls = new ObservableCollection<Ctrl>()
{
new Ctrl() {RGN_Index=1,RGN="RGN1", RSN="RSN1",SGN="SGN1",SN="SN1" },
new Ctrl() {RGN_Index=2,RGN="RGN2", RSN="RSN2",SGN="SGN2",SN="SN2" }
};
}
}
其次,当您获得光标焦点时,需要更新此选定索引。让我们在VM中定义ICommand:
// Here I am binding using Prism.Commands.DelegateCommand
public ICommand GotFocusCommand {get; private set;} = new Prism.Commands.DelegateCommand<int?>(GotFocus_Execute);
private void GotFocus_Execute(int? index)
{
if(index != null)
SelectedIndex = index.Value;
}
您可以注意到绑定需要相对资源
到项控件
的数据上下文
。原因是DataTemplate
的DataContext
仅限于ListControl
,并且命令
不是在ListControl
中定义的,而是在VM中定义的。您可以将命令改为静态,但我将跳过此步骤
第四,您必须具有要插入的按钮。因此,让我们首先在VM中定义命令:
private int SelectedIndex {get; set;} = -1; // only accessed internally, so private is good enough
public ICommand InsertCommand { get; private set; } = new Prism.Commands.DelegateCommand(InsertCommand_Execute);
private void InsertCommand_Execute()
{
if (SelectedIndex > 0)
{
// Insert at the selected index. Note that the Ctrl inserted is just for example
ListControls.Insert(SelectedIndex,
new Ctrl()
{
RGN_Index = ++last_index, // or whatever
RGN = $"RGN{last_index}", // or whatever
RSN = $"RSN{last_index}", // or whatever
SGN = $"SGN{last_index}", // or whatever
SN = $"SN{last_index}" // or whatever
});
}
}
private int last_index = 2; // this is just example. You might not even need this.
然后将此命令绑定到xaml上的按钮:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<TextBox Text="{Binding RGN}" Grid.Column="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="GotFocus">
<i:InvokeCommandAction Command="{Binding Path=DataContext.GotFocusCommand, Mode=OneTime, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" CommandParameter="{Binding RGN_Index}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<Button Content="Insert" Command="{Binding Path=InsertCommand, Mode=OneTime}"/>
完成了
需要考虑的事项:
当你点击按钮时,你的光标肯定不再聚焦在文本框上了。这样行吗
与第一个相关的是,始终记录最后一个聚焦的选定索引,因此,如果您单击文本框以外的任何内容,然后单击“插入”按钮,它仍然可以工作。这样行吗
你所需要担心的就是在视图模型的列表控件中插入中间的第三项。是的,我就是这么想的。因此,我需要获取RGN_索引,以便知道应该在ViewModel列表中的何处添加项。您可以使用绑定observablecollection的默认collectionview来获取特定项的索引。然后可以插入较低的索引。您需要对上方或下方行的viewmodel进行引用。在下一行的datacontext中使用控件,而不是在两行之间使用控件。我可以澄清一件事吗,当您说“光标聚焦”时,是鼠标悬停(未单击任何内容)还是鼠标悬停(与所选项目类似)?只是一个旁注:请始终提供一个最小的示例(请参阅)。例如,XAML中的FontSize
和Margin
实际上并不需要显示您的问题,它们只是夸大了示例,使其更难阅读。感谢您提供的解决方案。我用了你的主意。它成功了
<Button Content="Insert" Command="{Binding Path=InsertCommand, Mode=OneTime}"/>