【问题标题】:WPF Binding 2 Columns to ListViewWPF 将 2 列绑定到 ListView
【发布时间】:2014-02-10 17:01:42
【问题描述】:

XAML:

<ListBox x:Name="MyTitleBox" ItemsSource="{Binding}"/>
<ListBox x:Name="MyInfoBox" ItemsSource="{Binding}"/>

在 C# 中:

 MyTitleBox.ItemsSource = new List<string>(new string[] {"ID:", "Info:", "More Info:"});
 MyInfoBox.ItemsSource = new ObservableCollection<string>(MyMainInfo.ToString().Split(',').ToList<string>());

我目前有 2 个彼此相邻的列表框,因为我需要以编程方式处理它们的 ItemsSource。

我知道必须有更好的方法来合并两者。本质上,“左侧”的列表框是 ID 之类的标题:而“右侧”的列表框是信息。

我认为我可以像我所见的那样执行 MyTitleBox.Columns.Add 之类的操作,但它不允许我执行 .Columns。我正在使用 .NET 4。

【问题讨论】:

  • 请阅读ItemTemplateDataTemplate。这个link 将帮助您入门。
  • 我有。我的问题是它需要在 XAML 中定义,而不是以编程方式。
  • 这就是我的建议。 ItemTemplate 仅适用于 XAML。
  • 我正在以编程方式设置 ItemsSource。我需要能够在代码中设置数据源,因为数据源之前不存在。 DataTemplate 让我在 XAML 中设置数据源。

标签: c# .net wpf .net-4.0


【解决方案1】:

这是一个使用更多 MVVM 方法的示例:

域(您要放入列表的项目类型):

public class Movie : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _title;

    public string Title
    {
        get { return _title; }
        set
        {
            if (_title != value)
            {
                _title = value;

                RaisePropertyChanged("Title");
            }                
        }
    }

    private string _info;

    public string Info
    {
        get { return _info; }
        set
        {
            if (_info != value)
            {
                _info = value;

                RaisePropertyChanged("Info");
            }                
        }
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

视图模型:

public class MyViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<Movie> _movies;

    /// <summary>
    /// Collection of movies.
    /// </summary>
    public ObservableCollection<Movie> Movies
    {
        get { return _movies; }
        set
        {
            if (_movies != value)
            {
                _movies = value;

                RaisePropertyChanged("Movies");
            }
        }
    }

    /// <summary>
    /// Constructor
    /// </summary>
    public MyViewModel()
    {
        Movies = new ObservableCollection<Movie>();

        Movies.Add(new Movie() { Title = "Gravity", Info = "Gravity is about..." });
        Movies.Add(new Movie() { Title = "Avatar", Info = "Avatar is about..." });
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

XAML:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackOverflow"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ListBox ItemsSource="{Binding Movies}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock>
                        <Run Text="{Binding Title}" /><Run Text=" - " /><Run Text="{Binding Info}" />
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <Button Grid.Row="1" Content="Click To Change Info" Margin="5" Click="Button_Click" />
    </Grid>
</Window>

代码隐藏:

public partial class MainWindow : Window
{
    public MyViewModel ViewModel { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        ViewModel = new MyViewModel();

        DataContext = ViewModel;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Movie movie = ViewModel.Movies.FirstOrDefault();

        if (movie != null)
        {
            movie.Info = "This is the new information";
        } 
    }
}

实现 INotifyPropertyChanged 允许代码在发生变化时通知 UI。

如果您测试此代码,您将看到单击该按钮会更新第一部电影的信息,并且此更改会立即反映在 UI 中。 (通常您会使用命令之类的约定来处理按钮单击,但为简单起见,我这样做了)

如果您有任何问题,请告诉我。

【讨论】:

  • 谢谢,但好吧,我这样做了,但是现在如何设置绑定?由于 {Binding Title} 和 {Binding Info},.ItemsSource = list 不再做任何事情。你如何在 C# 而不是 XAML 中以编程方式设置它?
  • 您正在使用什么对象?这是一部电影还是有标题和信息的东西?老实说,您应用这些项目的方式并不好。
  • 所以我有 2 个字符串列表。列表 A 是标题,列表 B 是按特定顺序与标题对应的信息。列表 B 的字符串每隔 X 秒就会不断变化。程序启动时它们不存在。它们就像我在 OP 中的放置方式一样。所以 myAList[0] 对应于 myBList[0] 例如(ID:25),它是绑定到列表视图的集合中的第一项。这就是为什么现在我将它们并排放置,但这根本没有效率或很好寻找这件事。我正在努力学习如何清理它。
  • 我会给你一个首选方法的例子,这意味着使用 MVVM 方法。
  • 谢谢你,这将是非常有帮助的。我一直在学习 MVVM,但在这种特殊情况下如何使用它还不是很清楚。我只知道任何东西都比 200+ 值的一些 n^2 串联更好,只是为了让它看起来漂亮。一个例子将是无价的。
猜你喜欢
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 2018-06-09
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多