简体   繁体   English

WPF 将 SelectedItem 绑定到另一个对象的属性

[英]WPF Binding SelectedItem to a property of another object

What I'd like to do is lookup a "Category" to bind the SelectedItem to based on CurrentItem.CategoryId where that would match with Category.Id.我想要做的是查找“类别”以根据 CurrentItem.CategoryId 将 SelectedItem 绑定到与 Category.Id 匹配的位置。

<ListBox ItemsSource="{Binding Categories}" SelectedItem="{Binding CurrentItem.CategoryId, Mode=TwoWay>

I thought of using an IValueConverter, but I'm not sure how to pass the Category.Id as a ConverterParameter.我想过使用 IValueConverter,但我不确定如何将 Category.Id 作为 ConverterParameter 传递。 Or if that's even the right approach.或者,如果这甚至是正确的方法。 I have to imagine this is a common use case, but I don't even know what to google for.我不得不想象这是一个常见的用例,但我什至不知道该用谷歌搜索什么。 Any suggestions welcome!欢迎任何建议!

Edit: Ok, more details with full code then.编辑:好的,然后有完整代码的更多详细信息。 Transactions have a property called "CategoryId", which match an "Id" property on the Category type.交易有一个名为“CategoryId”的属性,它匹配类别类型上的“Id”属性。 My end goal is to get the selectedItem in the list box to be whatever Category the current SelectedTransaction in the DataGrid refers to.我的最终目标是让列表框中的 selectedItem 成为 DataGrid 中当前 SelectedTransaction 所指的任何类别。

It should be a two way binding, the ListView should be initialized to the Category the Transaction.CategoryId poitns to, and if the ListView is updated, then the Transaction.CategoryId property should be updated.它应该是双向绑定,ListView 应该被初始化为 Transaction.CategoryId 指向的 Category,如果 ListView 被更新,那么 Transaction.CategoryId 属性应该被更新。 Hopefully that's clear.希望这很清楚。

TransactionWindow.xaml事务窗口.xaml

<Window x:Class="Budgeter.TransactionsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Budgeter"
        mc:Ignorable="d"
        Title="TransactionsWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10px" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="10px" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="10px" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="10px" />
        </Grid.RowDefinitions>
        <DataGrid x:Name="grid" ItemsSource="{Binding Transactions}" AutoGenerateColumns="False" SelectionUnit="FullRow" SelectionMode="Single" Grid.Row="1" Grid.Column="1" Grid.RowSpan="4" SelectedItem="{Binding SelectedTransaction}" SelectionChanged="grid_SelectionChanged">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Date" Binding="{Binding Date}" Width="*" IsReadOnly="True" />
                <DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="*" MinWidth="200" IsReadOnly="True" />
                <DataGridTextColumn Header="Amount" Binding="{Binding Amount}" Width="*" IsReadOnly="True" />
                <DataGridTextColumn Header="Category" Binding="{Binding Category.Description}" Width="*" IsReadOnly="True" />
            </DataGrid.Columns>
        </DataGrid>
        <DockPanel Grid.Row="1" Grid.Column="2" Grid.RowSpan="3" Margin="5">
            <TextBlock Text="Category:" DockPanel.Dock="Top" />
            <ListBox ItemsSource="{Binding Categories}" SelectedItem="{Binding ???" DockPanel.Dock="Bottom">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Description}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </DockPanel>
    </Grid>
</Window>

TransactionWindow.xaml.cs事务窗口.xaml.cs

    public partial class TransactionsWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        
        public IList<CategoryViewModel> Categories { get; }
        public IList<TransactionViewModel> Transactions { get; }
        public TransactionViewModel SelectedTransaction { get; set; }
        public TransactionsWindow(IList<CategoryViewModel> categories, IList<TransactionViewModel> transactions)
        {
            InitializeComponent();
            this.Categories = categories;
            this.Transactions = transactions;

            if (this.Transactions != null && this.Transactions.Count > 0)
            {
                this.SelectedTransaction = transactions[0];
            }
            this.DataContext = this;
            
        }

        private void grid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.OnPropertyChanged(nameof(SelectedTransaction));
        }

        protected void OnPropertyChanged(string name = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

This should work:这应该有效:

<ListBox ItemsSource="{Binding Categories}"
         SelectedValuePath="Id"
         SelectedValue="{Binding SelectedTransaction.CategoryId"}>

Note that SelectedIndex, SelectedItem and SelectedValue bind TwoWay by default.请注意 SelectedIndex、SelectedItem 和 SelectedValue 默认绑定 TwoWay。


The SelectedTransaction property should fire the PropertyChanged event: SelectedTransaction 属性应该触发 PropertyChanged 事件:

private TransactionViewModel selectedTransaction;

public TransactionViewModel SelectedTransaction
{
    get { return selectedTransaction; }
    set
    {
        selectedTransaction = value;
        OnPropertyChanged(nameof(SelectedTransaction));
    }
}

You should also consider to move all those TransactionsWindow properties into another class and call it eg MainViewModel:您还应该考虑将所有这些 TransactionsWindow 属性移动到另一个类中并调用它,例如 MainViewModel:

DataContext = new MainViewModel();

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

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