我有一个用户控件,其中一个TextBox
和一个Button
名为View。 TextBox
获取索引值。
在我的Main
视图中,我有一个列表视图,它将显示文件中的所有行。
ObservableCollection
与此绑定。
我需要的是,当在TextBox
中输入索引值并且点击了视图Button
时(在用户控件中),SelecedIndex
ListView
(在Main中)应更改为索引值。
如何使用MVVM实现这一目标?
此外,如果我做错了,请提供正确的方法。
这是我的UserControl代码:
XAML
<UserControl.DataContext>
<VM:IndexView_VM ></VM:IndexView_VM>
</UserControl.DataContext>
<Grid Background="White">
<TextBlock Margin="10,12,168,9" Text="Index : "/>
<TextBox Text="{Binding Index}" x:Name="TB_Index" Margin="53,11,90,8" />
<Button Command="{Binding View_CMD}" x:Name="BT_View" Content="View" Margin="136,11,10,8" />
</Grid>
视图模型
public class IndexView_VM : ViewModelBase
{
public IndexView_VM()
{
View_CMD = new RelayCommand(_View_CMD);
}
int _Index;
public int Index
{
get { return _Index; }
set
{
_Index = value;
RaisePropertyChanged();
}
}
public RelayCommand View_CMD { get; set; }
internal void _View_CMD(object Parameter)
{
// What to write here?
}
}
以下是主视图:
XAML
<UserControl.DataContext>
<VM:MainView_VM></VM:MainView_VM>
</UserControl.DataContext>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="111*"/>
<ColumnDefinition Width="100*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<local:IndexView/>
<local:IndexView/>
<local:IndexView/>
<local:IndexView/>
</StackPanel>
<ListView ItemsSource="{Binding FileData}" x:Name="listView" Grid.Column="1" >
<ListView.View>
<GridView>
<GridViewColumn Header="Data" Width="100"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
查看模型
public class MainView_VM : ViewModelBase
{
public MainView_VM()
{
ReadFile();
}
public ObservableCollection<string> FileData { get; set; }
void ReadFile()
{
//I will read file here.
}
}
答案 0 :(得分:0)
如果您使用的是MvvmLight
,您可以使用Messenger
类将子视图模型中的消息发送给父级:
<强> IndexView_VM:强>
internal void _View_CMD(object Parameter)
{
GalaSoft.MvvmLight.Messaging.Messenger.Default.Send(_Index);
}
<强> MainView_VM:强>
public class MainView_VM : ViewModelBase
{
public MainView_VM()
{
ReadFile();
GalaSoft.MvvmLight.Messaging.Messenger.Default.Register<int>(this, index => Index = index);
}
public ObservableCollection<string> FileData { get; set; }
int _Index;
public int Index
{
get { return _Index; }
set
{
_Index = value;
RaisePropertyChanged();
}
}
void ReadFile()
{
//I will read file here.
}
}
<强>的MainView:强>
<ListView ItemsSource="{Binding FileData}" x:Name="listView" Grid.Column="1"
SelectedIndex="{Binding Index}">
<ListView.View>
<GridView>
<GridViewColumn Header="Data" Width="100"/>
</GridView>
</ListView.View>
</ListView>
有关Messenger
的更多信息,请参阅Laurent Bugnion的MSDN杂志文章。
MVVM - MVVM中的Messenger和View Services: https://msdn.microsoft.com/en-us/magazine/jj694937.aspx
答案 1 :(得分:0)
不确定我是否理解这一点。您想使用您在ListBox
中输入的索引值设置TextBox
的所选项目,这是对吗?
如果这是正确的,那么我有以下注意事项:
UserControl
可能有点过分。 特别是,如果你永远不会在你的UI中的其他地方重复使用它。TextBox
移至主视图,为其命名并将.Text
属性绑定到ListView
的{{1}} SelectedIndex
1}}财产。示例:
<ListView SelectedIndex="{Binding ElementName=txtIndex, Path=Text, Converter={StaticResource StringToIntConverter}, UpdateSourceTrigger=PropertyChanged}" />
需要转换器(您需要实现),因为将string
转换为int
不会自动发生。 UpdateSourceTrigger=PropertyChanged
会在您输入后立即更新目标属性,无需按钮。
此时你应该完成。
如果您绝对需要UserControl
,则可以添加DependencyProperty
公开TextBox
的值。然后你可以绑定到该属性,如上例所示。
答案 2 :(得分:0)
以下是您要执行的操作的基本示例:
Window XAML
<Window.Resources>
<local:StringToIntConverter x:Key="StringToIntConverter" />
</Window.Resources>
<StackPanel>
<TextBlock>Select Index</TextBlock>
<TextBox x:Name="theTextBox" Text="{Binding SelectedIndex,ElementName=theList,Converter={StaticResource StringToIntConverter},Mode=OneWayToSource,UpdateSourceTrigger=Explicit}" />
<Button Click="Button_Click">Select Now</Button>
<ListBox x:Name="theList">
<ListBoxItem>First</ListBoxItem>
<ListBoxItem>Second</ListBoxItem>
<ListBoxItem>Third</ListBoxItem>
</ListBox>
</StackPanel>
Window CodeBehind
private void Button_Click(object sender, RoutedEventArgs e)
{
theTextBox.GetBindingExpression(TextBox.TextProperty)?.UpdateSource();
}
<强>解释强>
您要求通过单击按钮从文本框中设置列表中的索引。我们使用几个设置将TextBox绑定到选定的索引:
要更新绑定,我们使用按钮的Click事件。
但视图模型呢? 该操作是一个View-Only操作,ViewModel不需要知道任何关于它的信息,因此我们应该将其排除在操作之外。这就是我没有使用CommandBinding的原因。
哎呀,忘了UserControl
如果你想把它放在一个用户控件中,那么我建议你根本不创建一个ViewModel。同样在用户控件中,您不需要DataBinding,仅在外部。保持简单:
UserControl XAML
<TextBlock>Select Index</TextBlock>
<TextBox x:Name="theTextBox" />
<Button Click="Button_Click">Select Now</Button>
UserControl CodeBehind
public int Index
{
get { return (int)GetValue(IndexProperty); }
set { SetValue(IndexProperty, value); }
}
public static readonly DependencyProperty IndexProperty =
DependencyProperty.Register("Index", typeof(int), typeof(ListViewIndexSelectorControl), new PropertyMetadata(0));
private void Button_Click(object sender, RoutedEventArgs e)
{
if(int.TryParse(theTextBox.Text, out int result))
{
Index = result;
}
}
MainWindow用法XAML
<local:ListViewIndexSelectorControl Index="{Binding SelectedIndex,ElementName=theList,Mode=OneWayToSource}" />
<ListBox x:Name="theList">
<ListBoxItem>First</ListBoxItem>
<ListBoxItem>Second</ListBoxItem>
<ListBoxItem>Third</ListBoxItem>
</ListBox>
如果您以后需要ViewModel,您也可以使用View作为ViewModel进行简单控制,只需在View的构造函数中设置DataContext = this;
或使用XAML元素上的Name并绑定ElementName的DataContext。