【问题标题】:Update TextBox text when a ComboBox's value is changed更改 ComboBox 的值时更新 TextBox 文本
【发布时间】:2014-08-27 20:28:32
【问题描述】:

我的应用:商店有一个 Products 集合和一个 int Id 属性。产品具有字符串 ProductCode 和 Description 属性。 ViewModel 引用 Store 的单个实例。 ViewModel 有一个静态的产品集合 (ProductList)。我的 View 的 DataContext 设置为 ViewModel。 My View 通过 ViewModel 显示 Store。

什么有效:我的视图有一个 TextBlock 绑定到 Store 的 Id。

什么不起作用:我的视图有一个 DataGrid,用于将产品添加到商店的产品集合中。用于将产品添加到 Store 的 Products 集合的 DataGrid 允许我使用 DataGridComboBoxColumn 列选择新的 ProductCode。这工作正常。但是,我希望我选择的 ProductCode 更新绑定到产品描述的 DataGridTextBoxColumn。

我花了几个小时在网上搜索,但没有找到任何与我的场景完全匹配的东西,除了可能来自此链接的“示例 12”,但我还没有让它适用于我的项目:Best ComboBox Tutorial Ever

已解决:

对我的代码最重要的更改是在为产品设置 ProductCode 后触发的 RefreshDescription 方法。此方法将 ProductCode 作为参数并查询静态 ProductList 以找到第一个匹配的描述。如果需要,用户可以更改自动填充的描述属性。

我认为的代码 sn-p:

<StackPanel>
    <TextBlock Text="{Binding Store.Id}"/>
    <DataGrid ItemsSource="{Binding Store.Products}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridComboBoxColumn 
                Header="ProductCode"
                ItemsSource="{x:Static m:ItemsProvider.ProductList}" 
                SelectedValueBinding="{Binding ProductCode,  UpdateSourceTrigger=PropertyChanged}" 
                SelectedValuePath="ProductCode"
                DisplayMemberPath="ProductCode"/>
        <!-- 
        I want Description for my chosen Product to pop in automatically... but how? 
        -->
            <DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
        </DataGrid.Columns>
    </DataGrid>
</StackPanel>

我的视图模型:

public class ViewModel : NotifyObject
{
    // Constructor
    public ViewModel()
    {
        _store = new Store() { Id = 1 };
    }
    
    // Fields
    Store _store;
    Product _selectedProduct;
    
    // Properties
    public Store Store {
        get { return _store; }
        set {
            _store = value;
            base.NotifyPropertyChanged("Commission");
        }
    }   
}

我的产品型号:

public class Product : NotifyObject
{
    // Constructor
    public Product() { }
    
    // Fields
    string _productCode;
    string _description;
    
    // Properties
    public string ProductCode { 
        get { return _productCode; }
        set {
            _productCode = value;       
            base.NotifyPropertyChanged("ProductCode");
            RefreshDescription(ProductCode);
        }
    }
    
    public string Description {
        get { return _description; }
        set {
            _description = value;
            base.NotifyPropertyChanged("Description");
        }
    }
    
   // Private Methods
    void RefreshDescription(string productCode)
    {
        if (ItemsProvider.ProductList.Count == 0) {
            return;
        }
        Product product = ItemsProvider.ProductList.FirstOrDefault(p => p.ProductCode == productCode);
        this.Description = (product == null ? "" : product.Description);
    }
}

我的商店模型:

public class Store : NotifyObject
{
    // Constructor
    public Store()
    {
        Products = new ObservableCollection<Product>();
    }
    
    // Fields
    int _id;
    
    // Properties       
    public int Id { 
        get { return _id; }
        set {
            _id = value;
            base.NotifyPropertyChanged("Id");
        }
    }
    
    public ObservableCollection<Product> Products { get; set; }     
}

用于获取可供选择的产品列表的静态类:

public static class ItemsProvider
{
    static ObservableCollection<Product> _productList = new ObservableCollection<Product>();
    static ItemsProvider() 
    {
        _productList = new ObservableCollection<Product>() {
            new Product() { ProductCode = "111", Description = "a" },
            new Product() { ProductCode = "222", Description = "b" },
            new Product() { ProductCode = "333", Description = "c" },
            new Product() { ProductCode = "444", Description = "d" }                    
        };
    }
    public static ObservableCollection<Product> ProductList {
        get {
            return _productList;
        }           
    }           
}

【问题讨论】:

  • 您可以通过任何可能的方式发布您所解释内容的屏幕截图吗?
  • 在分配ProductCode时,通过在Combobox中改变它,使其刷新描述。当然,产品类需要实现 InotifyPropertyChanged 以便任何更改都可以反映在 DataGrid 中,因为 ObservableCollection 无法做到。
  • @Maximus 你是对的;这就是我想要完成的。 Product 类实现 INotifyPropertyChanged。
  • 有点好笑,我只是解释了该怎么做。当您使用 Combobox 更改属性 ProductCode 时,您需要刷新 Description。在 ProducCode 的实现中添加代码,强制根据 ProdutCode 值更改 Description 值。当您更改它时,InotifyPropertyChanged 将让 DataGrid 知道更改,前提是您为 Desctiption 应用了通知。
  • 错字?公共商店商店 { 得到 { 返回 _store; } 设置 { _store = 值; NotifyPropertyChanged("Store"); } 您是否还对所有 Product 属性实施了 NotifyPropertyChanged?

标签: c# wpf wpfdatagrid


【解决方案1】:

一种简单的方法是在产品代码更改时引发PropertyChanged,然后进行查找以获取描述:

// Properties
public string ProductCode { 
    get { return _productCode; }
    set {
        _productCode = value;       
        base.NotifyPropertyChanged("ProductCode");
        base.NotifyPropertyChanged("Description");
    }
}

public string Description {
    get { 
        var matchingProduct = ViewModel.ProductList.FirstOrDefault(product => product.ProductCode == ProductCode);
        return (matchingProduct == null ? "" : matchingProduct.Description);
    }
}       

可能更好的方法是为您的 ProductList 和 Products 集合定义一个不同的类。前者应该是ProductType(包含产品代码和描述),后者应该是ProductInstance(只包含产品代码)。然后你可以使用类似上面的东西来定义后一个类的只读产品描述。

【讨论】:

  • 我想我已经弄清楚了。你在正确的轨道上,但这并不完美,因为如果她愿意,我需要让用户输入不同的描述。我明天会发布我的解决方案 - 必须回家休息一天。谢谢 McGarnagle 和 @Maximus!
  • 感谢 @McGarnagle 和 Maximus 的贡献!我赞成您的回答和评论。请在我的问题中的“已解决”下查看我的 cmets。 McGarnagle 的回答中唯一缺少的是描述的二传手;如果用户愿意,我不想取消用户将描述更改为自动填充值以外的其他内容的能力。
【解决方案2】:

来自我编辑的问题:

对我的代码最重要的更改是在为产品设置 ProductCode 后触发的 RefreshDescription 方法。此方法将 ProductCode 作为参数并查询静态 ProductList 以找到第一个匹配的描述。如果需要,用户可以更改自动填充的描述属性。

再次感谢那些帮助我得出这个结论的人!

【讨论】:

    猜你喜欢
    • 2013-11-30
    • 1970-01-01
    • 2016-10-23
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 2011-02-26
    相关资源
    最近更新 更多