【问题标题】:WPF MVVM Light dynamic views and datagridsWPF MVVM Light 动态视图和数据网格
【发布时间】:2014-08-22 01:51:09
【问题描述】:

好的,我这里有一个稍微复杂的功能。我想知道 A)如果我做得正确。如果不是,我应该改变什么? 2) 如果合适,我的问题的最佳解决方案是什么?

我有一个包含项目 ListView 的主窗口。如果我单击其中一个,则此窗口中的右侧网格列应填充 DataGrid,其中包含有关所选项目的信息。如果我单击 ListView 中的另一个项目,它应该会更改为另一个 DataGrid。

我已经看到了一些 ContentPresenter 示例,但我无法让它工作,所以我将其剥离出来,并向您展示我目前拥有的代码。现在,我只有一个项目设置,所以我将继续使用这个驱动程序示例。

DriverGrid.xaml

 <UserControl DataContext="{Binding AdminDriver, Source={StaticResource Locator}}">
     <Grid>

          <DataGrid>
               //stuff here for datagrid
          </DataGrid>

          <Button Content="Edit" Command="{Binding ShowEditWindow}" />
          <Button Content="Add"  Command="{Binding ShowAddWindow}"/>
     </Grid>
 </UserControl>

AdminDriver.cs (VM)

//Contains variables, and is the datacontext for the above usercontrol

AdminMain.xaml(查看所有管理内容)

//Contains a bunch of junk for the min admin screen which has the listview with the options in it.  If you require this piece of code, I can trim it down but I don't se currently see it's relevance.  The DataGrid belongs in this window, I'm assuming in a Content Presenter.  Here is the ListView that is in column 1 of 2.

 <ListView ItemsSource="{Binding AdminMenu}"
                          Name="AdminFields"
                          SelectionMode="Single">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="SelectionChanged">
                            <cmd:EventToCommand CommandParameter="{Binding SelectedItem, ElementName=AdminFields}" Command="{Binding registerSelected}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                    <ListView.ItemTemplate>
                        <ItemContainerTemplate>
                            <TextBlock Text="{Binding FieldName}"/>
                        </ItemContainerTemplate>
                    </ListView.ItemTemplate>
                </ListView>

【问题讨论】:

    标签: wpf xaml wpf-controls mvvm-light contentpresenter


    【解决方案1】:

    我会将 DataContext 的绑定从 UserControl 中取出。如果您发现需要,这将允许您在其他地方使用它。相反,只需在您使用它的地方绑定 DataContext。

    <view:YourUserControl DataContext="{Binding AdminDriver}" />
    

    如果您希望根据在 ListView 中选择的项目来呈现不同的 UserControl,那么您将使用 ContentPresenter。您的 ItemsSource 中的所有项目都将具有相同的基类或实现相同的接口,以便您可以将它们放在同一个 ObservableCollection 中。我会假设 AdminDriver 也属于那种类型/接口。

    您将在窗口顶部设置一些 DataTemplate,将 ItemsSource (AdminMenu) 中可能的对象的实际类型映射到代表它们的 UserControl。

    <Window.Resource>
       <DataTemplate DataType="{x:Type model:TypeA}">
          <view:UserControlA />
       </DataTemplate>
    
       <DataTemplate DataType="{x:Type model:TypeB}">
          <view:UserControlB />
       </DataTemplate>
       //rinse and repeat
    </Window.Resource>
    

    然后,您将向 Grid 添加一个 ContentPresenter 并将其 DataContext 绑定到 AdminDriver 属性。将出现与您的 DataTemplates 中映射的所选项目的实际类型相匹配的 UserControl。

    <ContentPresenter Content="{Binding AdminDriver}" />
    

    【讨论】:

    • 你能给我解释一下model:TypeA部分吗?我读了您的句子“您的 ItemsSource 中的所有项目都将具有相同的基类或实现相同的接口,以便您可以将它们放在同一个 ObservableCollection 中。” OC 的数据类型不同。并且集合没有“一个”基类。请注意,每个菜单项也将有一个 DataGrid/UserControl。相信我,我已经尝试过只使用一个,但根据我们的设计团队的要求,这不是一个选项。它需要被打破。
    • 所以 AdminMenu 集合是 ObservableCollection?你是说 registerSelected 命令根据 ListView 中的哪个项目被选中设置不同的属性吗?
    • 是:this.registerSelected = new RelayCommand((selectedMenuItem) => { this.SelectedMenuItem = selectedMenuItem.FieldName; });所以在我们的小例子中,this.SelectedMenuItem = "Driver"
    • 您将不得不显示更多代码。将其添加到问题中。这是您正在做的事情的关键组成部分。我想看看 AdminMenu 中的项目是什么样子的,在哪里设置了 AdminDriver,SelectedMenuItem = selectedMenuItem.FieldName 为你做什么?例如...为什么不直接将 SelectedItem 绑定到 SelectedMenuItem?
    • 好的,给我 5。除非你想搬到聊天室?
    猜你喜欢
    • 2014-10-11
    • 2016-05-12
    • 2015-02-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 2011-02-19
    • 2017-10-24
    相关资源
    最近更新 更多