【问题标题】:Binding to CurrentItem in a ItemsControl绑定到 ItemsControl 中的 CurrentItem
【发布时间】:2009-12-21 12:46:26
【问题描述】:

下面的 XAML 基本上是在尝试创建 Buttons 的列表(从当前 DataContext 中的 Views 集合中的对象的 Name 属性呈现。

当我点击一个按钮时,CollectionViewSourceCurrentItem 属性应该会发生变化,并且关联的 View 应该会显示在内容演示器中。

好的。如果我在下面的 XAML 中单击 ListBox,它会完全按预期工作。

但是,如果我单击 UniformGrid(由项目控件创建)中的按钮,CurrentItem 属性不会更新。

如何在ItemsControl 中选择项目时更新CurrentItem

谢谢

<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>

【问题讨论】:

    标签: wpf data-binding itemscontrol collectionviewsource currentitem


    【解决方案1】:

    你的按钮什么都不做。通常你的 ViewModel 会有一个名为 Select(或类似的东西)的 ICommand,Button 将被绑定到

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

    然后您将实例传递给您想要选择的 ICommand

    CommandParameter="{Binding}"

    它看起来像这样(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>
    

    ItemsControl 绑定到Models,因此Models 中的每个MyModel 都有一个按钮。按钮文本绑定到属性 Name。按钮命令绑定到 ViewModel 中的 Select 属性。当按钮被按下时,它调用 ICommand,发送按钮绑定的 MyModel 实例。

    请注意,在 UserControl 中使用 ViewModel 是一种代码味道UserControls 应该像所有其他控件一样出现在用户面前——它们应该具有绑定到用户的 ViewModel 的可绑定公共属性,而不是您的。然后绑定到UserControl 中这些属性的值。对于此示例,您将在 UserControl 上定义一个 ItemsSource 属性,ItemsControl 将绑定到该属性而不是直接绑定到 ViewModel

    【讨论】:

    • 是的,这就是我正在做的事情(在我的应用程序中而不是在示例中),但是我需要在每个视图模型中设置一个类似于“IsActiveView”的属性,并将其他视图模型保留在通过在每个节点上设置 IsActiveView=false 来同步。它开始滚雪球。我的示例中的 ListBox 可以满足我的需要。有没有办法让 Items 控件与它创建的项目保持同步?列表框的唯一问题是它不是水平的,并且它没有制作统一大小的区域。无论如何,我很欣赏这个想法。我会等很久,看看还有什么其他想法。谢谢
    • 有点难以掌握您在应用程序中尝试执行的操作。如果我想显示特定 MyModel 的详细信息,我将拥有一个公共 MyModel Selected {get;set;} 属性,并将 ContentControl 绑定到它。每种类型可以有不同的 DataTemplates,因此您绑定的任何类型的对象都将使用不同的 DataTemplate...
    • 好的,这行得通。但是,一个后续问题;如果我在屏幕上有五个按钮。每个都激活一个绑定到当前内容的视图(如您所建议的那样)。我想让代表活动视图的按钮突出显示。有没有办法可以使用触发器根据“选定”视图属性更改按钮的颜色。所以只有一个按钮是彩色的(突出显示为活动的。)它的行为就像一个选项卡控件,但我希望按钮在顶部均匀分布。 (这让我觉得我应该看看是否可以更改选项卡控件的模板以使用统一的网格
    • 可能是。这可能比仅仅在 ViewModel 上设置一个公共属性来指示应该突出显示哪个按钮,然后使用绑定到该公共属性的 Style DataTrigger 打开和关闭突出显示要困难得多...public enum Highlight { ViewA, ViewB, ViewC, ViewD }
    【解决方案2】:

    我认为你必须在代码隐藏中手动完成。

    XAML

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

    代码隐藏

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

    如果您使用 MVVM 模式和/或不想使用代码隐藏,您可以按照 Will 的建议将按钮的 Command 绑定到 ViewModel 中的命令

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-03
      • 2015-08-04
      • 2011-08-30
      • 2011-01-09
      • 2011-11-30
      • 2011-06-30
      • 1970-01-01
      • 2014-09-24
      相关资源
      最近更新 更多