WPF MVVM模式,有两个ListBox和一个TxtBox,选任一个ListBox的Item ,就显示在TextBox上。请帮帮高手。。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF MVVM模式,有两个ListBox和一个TxtBox,选任一个ListBox的Item ,就显示在TextBox上。请帮帮高手。。相关的知识,希望对你有一定的参考价值。

WPF MVVM模式,有两个ListBox和一个TxtBox,把两个ListBox中,选任一个的Item ,就显示在TextBox上。请帮帮高手。。。

参考技术A

下面的代码实现了绑定一个ListBox,要绑定两个你可以用Converter转换一下,就不给你示例了。

    <Grid>
        <ListBox Name="listBox1" SelectedValuePath="Content">
            <ListBox.Items>
                <ListBoxItem>aaa</ListBoxItem>
                <ListBoxItem>bbb</ListBoxItem>
                <ListBoxItem>ccc</ListBoxItem>
            </ListBox.Items>
        </ListBox>
        <TextBox Text="Binding ElementName=listBox1,
            Path=SelectedValue, Mode=OneWay"
           VerticalAlignment="Center"  HorizontalAlignment="Center"
                 MinWidth="50"/>
    </Grid>

追问

上面的代码我能做,我想要的是两个ListBox的。能帮帮吗?

追答

付费就给你做。

追问

我已经解决了,谢谢

追答

那行。

使用 MVVM 模式的 UI 设计

【中文标题】使用 MVVM 模式的 UI 设计【英文标题】:UI design using MVVM pattern 【发布时间】:2011-07-05 05:55:24 【问题描述】:

我正在尝试选择以 MVVM 方式实现此 UI 的最佳方式。我是 WPF 新手(比如 2 个月),但我有丰富的 WinForms 经验。

这里的ListBox 就像一个TabControl(因此它将视图切换到右侧),并且基本上包含表中显示的项目的类型。所有 UI 都是动态的(ListBox 项、TabItems 和 Columns 在运行时确定)。该应用程序的目标是 WPF 和 Silverlight。

ViewModel 需要的类:

public abstract class ViewModel : INotifyPropertyChanged 
public abstract class ContainerViewModel : ViewModel

    public IList<ViewModel> Workspaces get;set;
    public ViewModel ActiveWorkspace get;set;

public class ListViewModel<TItem> where TItem : class

    public IList<TItem> ItemList  get; set; 
    public TItem ActiveItem  get; set; 
    public IList<TItem> SelectedItems  get; set; 

public class TableViewModel<TItem> : ListViewModel<TItem> where TItem : class

    public Ilist<ColumnDescription> ColumnList  get; set; 

现在的问题是如何将其连接到 View。

我可以在这里看到两种基本方法:

使用 XAML:由于 XAML 中缺乏泛型支持,我将失去强类型。 没有 XAML:我可以重复使用相同的 ListView&lt;T&gt; : UserControl.

接下来,如何连接数据,我在这里看到了 3 种方法(这里有没有 XAML 都无所谓)。由于没有简单的 DataBinding 到 DataGrid 的列或 TabControl 的 TabItems 我看到的方法是:

将 DataBinding 与 IValueConverter 一起使用:我认为这不适用于 WPF|Silverlight 开箱即用的控件,因为我需要的某些属性是只读的或无法以双工方式绑定。 (对此我不确定,但我觉得它行不通)。

通过在视图中订阅 INotifyPropertyChanged 来使用手动逻辑:ViewModel.PropertyChanged+= ....ViewModel.ColumnList.CollectionChanged+= ....

使用支持此绑定的自定义控件:自己编写代码或查找支持此绑定的 3d 方控件(我不喜欢此选项,我的 WPF 技能太低,无法自己编写代码,我怀疑我自己会找到免费控件)


更新:28.02.2011 事情越来越糟,我决定用 TreeView 代替 ListBox,简直是一场噩梦。正如您可能猜到的那样,TreeView.SelectedItems 是一个只读属性,因此没有数据绑定。嗯,好吧,让我们用旧方法来订阅事件以将视图与视图模型同步。此时突然发现 DisplayMemberPath 对 TreeView 没有任何作用(嗯,好吧,让我们使用旧方式 ToString())。然后在 View 的方法中,我尝试将 ViewModel.SelectedItem 与 TreeView 同步:

private void UpdateTreeViewSelectedItem()

    //uiCategorySelector.SelectedItem = ReadOnly....

    //((TreeViewItem) uiCategorySelector.Items[uiCategorySelector.Items.IndexOf(Model.ActiveCategory)]).IsSelected = true;
    // Will not work Items's are not TreeViewItem but Category object......

    //((TreeViewItem) uiCategorySelector.ItemContainerGenerator.ContainerFromItem(Model.ActiveCategory)).IsSelected = true;
    //Doesn't work too.... NULL // Changind DataContext=Model and Model = new MainViewModel line order doesn't matter.
    //Allright.. figure this out later...

而且我能想到的方法都没有奏效......

这里是我演示使用 MVVM 控制库地狱的示例项目的链接:http://cid-b73623db14413608.office.live.com/self.aspx/.Public/MVVMDemo.zip

【问题讨论】:

我在 Silverlight 论坛上的类似主题:forums.silverlight.net/forums/64.aspx 【参考方案1】:

我写了一篇文章和一个带有可用源代码的示例应用程序,在那里我讨论并展示了我在这里提到的问题以及如何解决这些问题。

http://alexburtsev.wordpress.com/2011/03/05/mvvm-pattern-in-silverlight-and-wpf/

【讨论】:

【参考方案2】:

Maciek 和 Robert 已经为您提供了一些关于如何实现此功能的想法。

对于绑定 DataGrid 的列的细节,我强烈建议 Meleak's answer 解决该问题。

与此类似,您可以使用 attached properties(或 Behaviors)并在 MVVM 中仍然保持干净的 ViewModel。

我知道 WPF 的学习曲线非常陡峭,而您已经在苦苦挣扎。我也知道以下建议无济于事,甚至使曲线更陡峭。但是你的场景很复杂,我建议使用PRISM。

【讨论】:

感谢您的回复,我认为附加属性会完成这项工作,我并不是要维护干净的 View 或 ViewModel,我只是想完成这项工作。我不确定 PRISM(从未见过,但我知道它是 MVVM 框架),因为问题在于 WPF 的控件(如 DataGrid)设计不良,解决方案是使用\编写另一个表控件,或在一个中使用事件表单或其他(如附加属性) @Alex 不得不依赖行为形式的事件并不是一件坏事,因为行为是某种密封形式的代码,它本身很容易testable。当然,如果您只关心完成工作(您或其他任何人都不必维护该代码),您可以省去这个,因为它确实涉及一些开销。 +1 推荐使用 PRISM 来管理总体布局——“区域”管理让生活更轻松。我们同样需要动态绑定列,所以我们创建了一个自定义控件。这是相当多的工作,但如果它结束,您将了解更多关于 WPF 的信息 :)。如果时间紧迫,您可以打破 MVVM 模式以在代码中添加列,然后再找到更简洁的解决方案。【参考方案3】:

Maciek 的答案实际上比它需要的还要复杂。您根本不需要模板选择器。创建异构选项卡控件:

    为您希望显示为选项卡项的每种视图类型创建一个视图模型类。确保每个类都实现了一个 Text 属性,该属性包含您希望在其项目的选项卡中显示的文本。

    为每个视图模型类创建一个DataTemplate,将DataType设置为类的类型,并将模板放入资源字典中。

    使用视图模型的实例填充集合。

    创建一个TabControl 并将其ItemsSource 绑定到此集合,并添加一个ItemTemplate 以显示每个项目的Text 属性。

这是一个不使用视图模型的示例(也没有实现 Text 属性,因为我绑定到的对象是简单的 CLR 类型),但显示了模板选择在此上下文中的工作方式:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib">
  <DockPanel>  
   <DockPanel.Resources>
        <coll:ArrayList x:Key="Data">
          <sys:String>This is a string.</sys:String>
          <sys:Int32>12345</sys:Int32>
          <sys:Decimal>23456.78</sys:Decimal>
        </coll:ArrayList>
        <DataTemplate DataType="x:Type sys:String">
          <TextBlock Text="Binding"/>
        </DataTemplate>
        <DataTemplate DataType="x:Type sys:Int32">
          <StackPanel Orientation="Horizontal">
           <TextBlock>This is an Int32:</TextBlock>
           <TextBlock Text="Binding"/>
          </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="x:Type sys:Decimal">
          <StackPanel Orientation="Horizontal">
           <TextBlock>This is a Decimal: </TextBlock>
           <TextBlock Text="Binding"/>
          </StackPanel>
        </DataTemplate>
   </DockPanel.Resources>
    <TabControl ItemsSource="StaticResource Data">  
      <TabControl.ItemTemplate>
       <DataTemplate>
        <TextBlock Text="Binding"/>
       </DataTemplate>
      </TabControl.ItemTemplate>
    </TabControl>
  </DockPanel>
</Page>

当然,在真正的 MVVM 应用程序中,DataTemplates 会使用 UserControls 将每种类型映射到其视图:

<DataTemplate DataType="x:Type my:ViewModel">
   <my:View DataContext="Binding"/>
</DataTemplate>

【讨论】:

感谢您对TabControl的回复,但我更感兴趣的是:绑定DataGrid的列、排序列、DataGrid的选定行。 这行不通的是 Silverlight(我同时针对 WPF 和 Silverlight),Maciek 是对的,您需要使用 IValueConverter 或从 TabItem 派生。 啊,我没有看到 Silverlight 的必要性。这确实改变了一些事情。更好的模板选择确实会提高 SL。【参考方案4】:

为了将您的 ViewModel 连接到您的 View,您需要分配 View 的 DataContext。这通常在视图的构造函数中完成。

public View()

    DataContext = new ViewModel();

如果您想在设计时查看视图模型的效果,您需要在 XAML 中声明它,在视图的资源中,为其分配一个键,然后通过 StaticResource 设置目标的 DataContext。

<UserControl
xmlns:vm="clr-namespace:MyViewModels
>
    <UserControl.Resources>
         <vm:MyViewModel x:Key="MyVM"/>
    </UserControl.Resources>
    <MyControl DataContext=StaticResource MyVM/>
</UserControl>

(以上是为了演示设计时技巧的工作原理)

由于您正在处理包含容器(例如 TabControl)的场景,我建议您考虑以下事项:

将您的子 ViewModel 保存在 ObservableCollection 类型的属性中 将 TabControls ItemsSource 绑定到该属性 创建一个派生自 TabItem 的新视图 使用模板选择器根据视图模型的类型自动选择视图的类型。 将 IDisposable 添加到您的子 ViewModel 并创建关闭视图的功能。

希望对您有所帮助,如果您还有其他问题,请告诉我。

【讨论】:

是的,它确实有点帮助,我还没有听说过模板选择器。虽然我对 DataContext 并不陌生 :-) Alex,考虑下面的例子,你有一个视图 MyView,它有一个 ItemsControl 类型的控件(显示项目列表)。在 XAML 中,您编写: 。如果您的 MyItemsProperty 已正确初始化并包含项目,这可能不会产生所需的效果事件。这是因为 MyItemsControl 不知道它的 DataContext。在这种情况下,在 MyView 的构造函数中,您需要编写 MyItemsControl.DataContext = this。现在 MyItemsControl 知道在哪里查看(续) 如果您在同一场景下的同一视图中有多个控件,则需要重复 n 次。 MVVM 的目的是通过 ONE SWIFT STROKE (DataContext = new ViewModel()) 消除这种情况。视图中的所有控件都以 ViewModel 作为其 DataContext。 DataGrid 有点棘手,我会在 ChildView 中处理它并将其数据绑定到 ChildViewModel - 很大程度上取决于您使用的是什么 DataGrid,它是来自 WPF Toolkit 还是一个不同的,这个控件会变得非常讨厌。 如何绑定 DataGrid 的 Column 的排序列(我的 UI 逻辑中需要它)。我正在使用 Net 4.0 附带的 DataGrid。我知道如何绑定可以通过 ItemsSource 轻松绑定的东西,但是 ReadOnly 属性、不是 Dependency 属性的属性,或者像 DataGrid 的当前排序列这样根本没有属性的东西,让我卡住了。

以上是关于WPF MVVM模式,有两个ListBox和一个TxtBox,选任一个ListBox的Item ,就显示在TextBox上。请帮帮高手。。的主要内容,如果未能解决你的问题,请参考以下文章

(MVVM) ListBox Binding

WPF MVVM更新列表框

wpf 下拉多选控件!

WPF绑定第二个ListBox与第一个ListBox中的选定项目相关

wpf mvvm模式 Icommand接口应该如何理解?

wpf MVVM Viewmodel之间传值