简体   繁体   English

绑定到ItemsControl中的CurrentItem

[英]Binding to CurrentItem in a ItemsControl

The XAML below is basically trying to make a list of Button s (rendered from the Name property of objects in the Views collection in the current DataContext . 下面的XAML基本上是尝试创建Button的列表(从当前DataContextViews集合中的对象的Name属性呈现)。

When I click on a button the CurrentItem property of CollectionViewSource should change and the associated View should be displayed in a content presenter. 当我单击一个按钮时, CollectionViewSourceCurrentItem属性应该更改,关联的View应该显示在内容呈现器中。

OK. 好。 If I click in the ListBox in the XAML below it works exactly as desired. 如果我单击下面XAML中的ListBox ,它将完全按照需要工作。

But, If I click a button in the UniformGrid (created by the items control) the CurrentItem property is not updated. 但是,如果单击UniformGrid的按钮(由items控件创建),则不会更新CurrentItem属性。

How do I get the CurrentItem to be updated when an item is selected in the ItemsControl ? 如何在ItemsControl选择项目时更新CurrentItem

Thanks 谢谢

<UserControl x:Class="Pos.Features.Reservation.ReservationView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:product="clr-namespace:Pos.Features.ProductBrowser"
             xmlns:activity="clr-namespace:Pos.Features.ActivityBrowser"
             xmlns:addbysku="clr-namespace:Pos.Features.AddBySku"
             xmlns:client="clr-namespace:Pos.Features.ClientBrowser"
             xmlns:notes="clr-namespace:Pos.Features.Notes"
             xmlns:controls="clr-namespace:Pos.Views"
             xmlns:res="clr-namespace:Pos.Core;assembly=Pos.Core"
             Height="300" Width="300">
    <UserControl.Resources>
        <DataTemplate DataType="{x:Type product:ProductBrowserViewModel}">
            <product:ProductBrowserView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type activity:ActivityBrowserViewModel}">
            <activity:ActivityBrowserView/>
        </DataTemplate>

        <CollectionViewSource x:Name="x" x:Key="ViewsCollection" Source="{Binding Views}"  />
    </UserControl.Resources>

    <StackPanel>
        <ListBox Name="ListBoxMenu" Grid.Column="0" Margin="5" ItemsSource="{Binding Source={StaticResource ViewsCollection}}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" Padding="10"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <ContentControl Grid.Column="1" Content="{Binding ElementName=ListBoxMenu, Path=SelectedItem}"/>
        <ItemsControl  Grid.Column="2" Name="ViewList" ItemsSource="{Binding Source={StaticResource ViewsCollection}}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button>
                        <TextBlock Text="{Binding Path=Name}" Name="txtButtonLabel" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/>
                    </Button>
                </DataTemplate>                
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Rows="1" Columns="{Binding Views.Count}"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
        <ContentControl Grid.Column="3" Content="{Binding Source={StaticResource ViewsCollection}, Path=CurrentItem}"/>
        <Button Grid.Column="4" Click="Button_Click">dsadsd</Button>
    </StackPanel>
</UserControl>

Your button does nothing. 你的按钮什么也没做。 Usually your ViewModel would have an ICommand called Select (or something similar) that the Button would be bound against 通常,您的ViewModel会有一个名为Select(或类似名称)的ICommand,Button会被绑定

Command="{Binding Select, ElementName="root"}"

and you'd pass the instance to the ICommand that you'd like to select 然后你将实例传递给你想要选择的ICommand

CommandParameter="{Binding}"

It would look something like this (c#/XAML like pseudocode): 它看起来像这样(c#/ XAML像伪代码):

public class MyModel { public string Name {get;set;} }

public class MyViewModel
{
  public ObservableCollection<MyModel> Models {get;set;}
  public ICommand Select {get;set;}
  /* configure Models and Select etc */
}

<UserControl DataContext="{StaticResource MyViewModelInstance}" x:Name="root">
<ItemsControl ItemsSource="{Binding Models}">
  <ItemsControl.ItemTemplate>
    <ItemsPanelTemplate>
      <Button Text="{Binding Name}" 
      Command="{Binding Select, ElementName="root"}"
      CommandParameter="{Binding}"/>
   </ItemsPanelTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>

The ItemsControl binds to Models , so each MyModel in Models gets a button. ItemsControl的结合模式 ,因此在模型为MyModel得到一个按钮。 The button text is bound to the property Name . 按钮文本绑定到属性Name The button command is bound to the Select property in the ViewModel. button命令绑定到ViewModel中的Select属性。 When the button is pressed, it calls the ICommand, sending in the instance of MyModel that the button is bound against. 按下按钮时,它会调用ICommand,在MyModel实例中发送按钮绑定的内容。

Please do note that using ViewModels within a UserControl is a code smell . 请注意,在UserControl中使用ViewModels是一种代码味道 UserControl s should appear to users as all other controls--they should have bindable public properties which are bound to the user's ViewModel , not yours. UserControl应该作为所有其他控件向用户显示 - 它们应该具有绑定到用户的ViewModel的可绑定公共属性,而不是你的。 You then bind to the values of these properties within the UserControl . 然后绑定到UserControl中这些属性的值。 For this example, you would have an ItemsSource property defined on your UserControl , and the ItemsControl would bind to this property rather than a ViewModel directly. 对于此示例,您将在UserControl上定义ItemsSource属性,而ItemsControl将直接绑定到此属性而不是ViewModel

I think you have to do it manually in code-behind. 我认为你必须在代码隐藏中手动完成它。

XAML XAML

<Button Click="ViewListButton_Click">
    <TextBlock Text="{Binding Path=Name}" Name="txtButtonLabel" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/>
</Button>

Code-behind 代码隐藏

private void ViewListButton_Click(object sender, RoutedEventArgs e)
{
    Button button = sender as Button;
    ICollectionView view = CollectionViewSource.GetDefaultView(ViewList.ItemsSource);
    view.MoveCurrentTo(button.DataContext);
}

If you're using the MVVM pattern and/or you don't want to use code-behind, you could bind the button's Command to a command in your ViewModel, as suggested by Will 如果您正在使用MVVM模式和/或您不想使用代码隐藏,则可以将按钮的Command绑定到ViewModel中的命令,如Will所建议的那样

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM