简体   繁体   English

WPF在组合框中选择的值

[英]WPF selected value in ComboBox

I'am struggling with ComboBox in my DataGrid View. 我在DataGrid视图中正在使用ComboBox。

I have 2 Observable Collection. 我有2个可观察的集合。 One for Data Grid where column DDV presents selected item of Combobox and second where are all options for CombBox. 一个用于数据网格,其中DDV列显示Combobox的选定项,第二个是CombBox的所有选项。

Observable Collection DDV_Data (all ComboBox options) is in Observable Collection of ArtikliStoritveData. 可观察的集合DDV_Data(所有ComboBox选项)在ArtikliStoritveData的可观察的集合中。

My WPF looks like this: 我的WPF如下所示:

        <DataGrid ItemsSource="{Binding Path=ArtikliStoritveData}" AutoGenerateColumns="False" SelectionMode="Single" CanUserAddRows="True" x:Name="dgArtikliStoritve" HorizontalAlignment="Left" Margin="31,58,0,0" VerticalAlignment="Top" Height="229" Width="612">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Šifra" Binding="{Binding Sifra}" />
            <DataGridTextColumn Header="Naziv" Binding="{Binding Naziv}" Width="200"/>
            <DataGridTextColumn Header="Znesek" Binding="{local:CultureAwareBinding Path=Znesek, StringFormat={}{0:C}}"/>
            <DataGridTextColumn Header="DDV" Binding="{local:CultureAwareBinding Path=DDV}" />
            <DataGridTextColumn Header="EM" Binding="{Binding EM}" />
            <DataGridTextColumn Header="Datum spremembe" Binding="{local:CultureAwareBinding Path=DatumSpremembe}" />
            <DataGridTemplateColumn Header="DDV">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox
                            x:Name="cmbDDV"
                            ItemsSource="{Binding DDV_Data}"
                            SelectedValuePath="DDV"
                            DisplayMemberPath="DDV"
                            SelectedValue="{Binding DDV1}"
                            IsSynchronizedWithCurrentItem="True"
                            Width="50"
                        />
                        </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Binding="{Binding Artikel_ID}" Width="0" Visibility="Hidden"/>
            <DataGridTextColumn Binding="{Binding SkupinaArtikla}" Width="0" Visibility="Hidden"/>
        </DataGrid.Columns>
    </DataGrid>

And my result in DataGrid is: 我在DataGrid中的结果是:

在此处输入图片说明

It is obvious that selected item is not working. 很明显,所选项目不起作用。 What I'am doing wrong? 我做错了什么?

I am also wondering why ComboBox in new row doesn't get bind? 我也想知道为什么新行中的ComboBox无法绑定?

DDV_Data is part of Observable Collection which is binded to DataGrid: DDV_Data是Observable集合的一部分,该集合绑定到DataGrid:

                ArtikliStoritveData.Add(new ArtikliStoritve
                {    
                    Artikel_ID = Convert.ToInt32(dt.Rows[i]["artikel_id"].ToString()),
                    SkupinaArtikla = Convert.ToInt32(dt.Rows[i]["skupina_artikla"].ToString()),
                    Sifra = dt.Rows[i]["sifra"].ToString(),
                    EM = dt.Rows[i]["em"].ToString(),
                    Naziv = dt.Rows[i]["naziv"].ToString(),
                    DDV = Convert.ToDecimal(dt.Rows[i]["ddv"].ToString()),
                    DDV_Data = DDV_Data1,
                    SelectedItem = "22.0",
                    Znesek = Decimal.Parse(dt.Rows[i]["znesek"].ToString()) ,
                    DatumSpremembe = DateTime.Parse(dt.Rows[i]["date_changed"].ToString())
                });    

DDV Property in ArtikliStoritve model: ArtikliStoritve模型中的DDV属性:

    public decimal DDV
    {
        get { return _ddv; }
        set { _ddv = value; }

I have also noticed that when I change value in ComboBox ith changes in every row??? 我还注意到,当我更改ComboBox中的值时,每行都会发生更改???

ArtikliStoritve: ArtikliStoritve:

class ArtikliStoritve
{

    #region private varaibles
    int _artikel_id;
    int _skupinaArtikla;
    string _sifra;
    string _naziv;
    string _EM;
    decimal _ddv;
    decimal _znesek;
    DateTime _datum_spremembe;

    #endregion

    #region properties
    public int Artikel_ID
    {
        get { return _artikel_id; }
        set { _artikel_id = value; }
    }

    public int SkupinaArtikla
    {
        get { return _skupinaArtikla; }
        set { _skupinaArtikla = value; }
    }

    public string Sifra
    {
        get { return _sifra; }
        set { _sifra = value; }
    }

    public string EM
    {
        get { return _EM; }
        set { _EM = value; }
    }

    public string Naziv
    {
        get { return _naziv; }
        set { _naziv = value; }
    }

    public decimal DDV1
    {
        get { return _ddv; }
        set { _ddv = value; }
    }

    public decimal Znesek
    {
        get { return _znesek;}
        set { _znesek = value; }
    }

    public DateTime DatumSpremembe
    {
        get { return _datum_spremembe; }
        set { _datum_spremembe = value; }
    }

    private decimal _SelectedItem;
    public decimal SelectedItem
    {
        get { return _SelectedItem; }
        set { _SelectedItem = value; }
    }

    private ObservableCollection<DDV_Class> _DDV_Data = new ObservableCollection<DDV_Class>();
    public ObservableCollection<DDV_Class> DDV_Data
    {
        get { return _DDV_Data; }
        set { _DDV_Data = value; }
    }
    #endregion
}

For ComboBox I have a class: 对于ComboBox,我有一个课程:

class DDV_Class
{
    private int _ID;
    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }

    private decimal _DDV;
    public decimal DDV
    {
        get { return _DDV; }
        set { _DDV = value; }
    }
}

which i Fill in ArtikliStoritveViewModel: 我在ArtikliStoritveViewModel中填写以下内容:

for (int i = 0; i < dtDDV.Rows.Count; i++)
{
    DDV_Data1.Add(new DDV_Class
    {
        ID = Convert.ToInt32(dtDDV.Rows[i]["ID"].ToString()),
        DDV = Convert.ToDecimal(dtDDV.Rows[i]["DDV"].ToString())
    });
}

--> UPDATE ->更新

What I did. 我做了什么。 In ArtikliStoritve: 在ArtikliStoritve中:

private DDV_Class _SelectedItem;
public DDV_Class SelectedItem
{
    get { return _SelectedItem; }
    set { _SelectedItem = value; }
}

When filling: 填充时:

for (int i = 0; i < dt.Rows.Count; ++i)
{
    ArtikliStoritveData.Add(new ArtikliStoritve
    {
        Artikel_ID = Convert.ToInt32(dt.Rows[i]["artikel_id"].ToString()),
        SkupinaArtikla = Convert.ToInt32(dt.Rows[i]["skupina_artikla"].ToString()),
        Sifra = dt.Rows[i]["sifra"].ToString(),
        EM = dt.Rows[i]["em"].ToString(),
        Naziv = dt.Rows[i]["naziv"].ToString(),
        DDV1 = Convert.ToDecimal(dt.Rows[i]["ddv"].ToString()),
        DDV_Data = DDV_Data1,
        SelectedItem = new DDV_Class { ID = 1, DDV = 22.0m },
        Znesek = Decimal.Parse(dt.Rows[i]["znesek"].ToString()),
        DatumSpremembe = DateTime.Parse(dt.Rows[i]["date_changed"].ToString())
    });        
}

In ArtikliStoritveModelView I also have property: 在ArtikliStoritveModelView中,我还具有属性:

public DDV_Class SelectedItem
{
    get { return ArtikliStoritve.SelectedItem; }
    set { ArtikliStoritve.SelectedItem = value; OnPropertyChanged("SelectedItem"); }
}

WPF look like this: WPF看起来像这样:

<DataTemplate>
    <ComboBox
        x:Name="cmbDDV"
        ItemsSource="{Binding DDV_Data}"
        DisplayMemberPath="DDV"
        SelectedItem="{Binding Path=SelectedItem}"
        IsSynchronizedWithCurrentItem="True"
        Width="50"
    />
</DataTemplate>

Result is same like picture above is showing. 结果和上面的图片一样。

--> UPDATE I figure it out why value in all rows changed when I change value in comboBox in one row. ->更新我弄清楚了为什么在一行中更改comboBox中的值时所有行中的值都更改了。 Problem vas beacuse I added in each row one istance of Observable Collection: 由于我在每行中添加了一个Observable Collection的象,所以出现了问题:

DDV_Data1 is not instantiate for each row, so this is a problem - one object in all rows: DDV_Data1没有为每一行实例化,因此这是一个问题-所有行中都有一个对象:

DataTable dtDDV = myDDV_DAL.getAll();
if (dtDDV.Rows.Count > 0)
{
    for (int i = 0; i < dtDDV.Rows.Count; i++)
    {
        DDV_Data1.Add(new DDV_Class
        {
            ID = Convert.ToInt32(dtDDV.Rows[i]["ID"].ToString()),
            DDV = Convert.ToDecimal(dtDDV.Rows[i]["DDV"].ToString())
        });
    }
}

ArtikliStoritveDAL myArtikliStoritveDAL  = new ArtikliStoritveDAL();
DataTable dt = myArtikliStoritveDAL.getAll();
if (dt.Rows.Count > 0)
{
    for (int i = 0; i < dt.Rows.Count; ++i)
    {
        ArtikliStoritveData.Add(new ArtikliStoritve
        {
            ...
            DDV_Data = DDV_Data1,
            ...

I did my testing on another column where this is now working: 我在另一列可以进行测试的地方进行了测试:

EM_DAL myEM_DAL = new EM_DAL();
DataTable dtEM = myEM_DAL.getAll();
if (dtEM.Rows.Count > 0)
{
    for (int i = 0; i < dtEM.Rows.Count; i++)
    {
        EM_Data.Add(new EM_Model
        {
            ID = dtEM.Rows[i]["EM"].ToString(),
            Naziv = dtEM.Rows[i]["EM"].ToString()
        });
    }
}

    ArtikliStoritveDAL myArtikliStoritveDAL  = new ArtikliStoritveDAL();
DataTable dt = myArtikliStoritveDAL.getAll();
if (dt.Rows.Count > 0)
{
    for (int i = 0; i < dt.Rows.Count; ++i)
    {
        ArtikliStoritveData.Add(new ArtikliStoritve
        {
            ...
            EM_Data = getAll(dt.Rows[i]["em"].ToString()),
            ...


public List<EM_Model> getAll(string p_selected)
{
    List<EM_Model> myEM_Model = new List<EM_Model>();
    string strConnString = Util.getConnectionString();
    try
    {
        NpgsqlConnection conn = new NpgsqlConnection(strConnString);
        DataTable dt = new DataTable();
        conn.Open();
        NpgsqlDataAdapter da = new NpgsqlDataAdapter("SELECT em, em "
                                                        + " FROM em", conn);
        da.Fill(dt);
        conn.Close();
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            myEM_Model.Add(new EM_Model
            {
                ID = dt.Rows[i]["EM"].ToString(),
                Naziv = dt.Rows[i]["EM"].ToString(),
                SelectedItem1 = p_selected
            });
        }
        return myEM_Model;

Now I must figure it out why is value is not getting selected in comboBox. 现在,我必须弄清楚为什么未在comboBox中选择值。 I tested with selected value created in object where all options for comboBox is (getAll()) or in collection ArtikliStoritveData. 我测试了在comboBox的所有选项为(getAll())的对象中或在集合ArtikliStoritveData中创建的选定值的情况下进行了测试。 Neither one is working. 没有人在工作。

Keep searching for right solution... :) 继续寻找正确的解决方案... :)

If I serach contect in one row, Snoop showing me this(which is right): 如果我连续进行搜索,Snoop会向我显示以下内容(正确):

在此处输入图片说明

If do this in WPF, selected value in Combobox is first value in list, not the correct one: 如果在WPF中执行此操作,则“组合框”中的选定值是列表中的第一个值,而不是正确的值:

<ComboBox
    x:Name="cmbEM"
    ItemsSource="{Binding EM_Data}"
    DisplayMemberPath="Naziv"
    SelectedItem="{Binding EM}"
    IsSynchronizedWithCurrentItem="True"
    Width="50"
/>

And finally I found a solution. 最后我找到了解决方案。 Conjuction of SelectedValue and SelectedValuePath did the trick. 结合使用SelectedValue和SelectedValuePath可以达到目的。

<ComboBox
    x:Name="cmbDDV"
    ItemsSource="{Binding DDV_Data}"
    DisplayMemberPath="DDV"
    SelectedValue="{Binding DDV, Mode=TwoWay}" 
    SelectedValuePath="DDV" 
    IsSynchronizedWithCurrentItem="True"
    Width="50"
/>

On the link I found additional informations which helped me. 在该链接上,我发现了有助于我的其他信息。

Regards, Igor 问候,伊戈尔

I think I can see where your error is... when data binding to a ComboBox.SelectedItem property, there are a few things to note. 我想我可以看到您的错误在哪里...将数据绑定到ComboBox.SelectedItem属性时,需要注意一些事项。 The first is that the object data bound to the SelectedItem property must be of the same type as the items in the collection that is data bound to the ItemsSource property. 首先是绑定到SelectedItem属性的对象数据必须与集合中绑定到ItemsSource属性的数据的项目具有相同的类型

From your code, it seems as though the collection you data bound to the ItemsSource property was of the type of a custom class... you didn't show that, but I guessed because you set the DisplayMemberPath to a value of Naziv . 从您的代码看来,您绑定到ItemsSource属性的数据的集合似乎是自定义类的类型……您没有显示出来,但是我猜是因为您将DisplayMemberPath设置为Naziv的值。 So either you'd need to make your DDV property that you data bind to the SelectedItem property the same type as the items in the collection , or you could try using the ComboBox.SelectedValue property in conjunction with the SelectedValuePath property instead: 因此,要么需要使数据绑定到SelectedItem属性的DDV属性与集合中各项的类型相同,要么可以尝试将ComboBox.SelectedValue属性与SelectedValuePath属性结合使用:

<ComboBox x:Name="cmbDDV" 
    ItemsSource="{Binding Path=DDV_Data}"
    DisplayMemberPath="Naziv"
    SelectedValuePath="Naziv"
    IsSynchronizedWithCurrentItem="True"
    SelectedValue="{Binding Path=DDV}"
    Width="50" />

UPDATE >>> 更新>>>

Your latest edit is not what I suggested. 您最近的修改不是我建议的。 All the same, now that you've added the relevant code, I can see that ArtikliStoritveData is a collection of type ArtikliStoritve and DDV_Data is a property in that class which is a collection of type DDV_Class . 一样,现在您已经添加了相关代码,我可以看到ArtikliStoritveDataArtikliStoritve类型的集合,而DDV_DataDDV_Data中的属性,该属性是DDV_Class类型的DDV_Class Therefore, you need a property also of type DDV_Class in your ArtikliStoritve class that you can bind to the SelectedIten property: 因此,您还需要在ArtikliStoritve类中也具有DDV_Class类型的属性,该属性可以绑定到SelectedIten属性:

<ComboBox x:Name="cmbDDV" 
    ItemsSource="{Binding Path=DDV_Data}"
    SelectedItem="{Binding Path=SelectedItem}"
    IsSynchronizedWithCurrentItem="True"
    Width="50" />

...

private DDV_Class _SelectedItem;
public DDV_Class SelectedItem
{
    get { return _SelectedItem; }
    set { _SelectedItem = value; }
}

private ObservableCollection<DDV_Class> _DDV_Data = new ObservableCollection<DDV_Class>();
public ObservableCollection<DDV_Class> DDV_Data
{
    get { return _DDV_Data; }
    set { _DDV_Data = value; }
}

Just a couple of things to note here for the future... if you want to set the ComboBox.SelectedItem from the code, the item that you set as the value must be an actual item from the collection that is bound to the ComboBox.ItemsSource property. 未来有两件事要注意...如果要从代码中设置ComboBox.SelectedItem ,则设置为值的项目必须是绑定到ComboBox.ItemsSource 的集合的实际项目 ComboBox.ItemsSource属性。 You can do it like this: 您可以这样做:

SelectedItem = DDV_Data.Where(d => d.ID == someIdValue).Single();

Also, you should have got some errors displayed in the Output Window in Visual Studio... something like: 另外,您应该在Visual Studio的“输出”窗口中显示一些错误,例如:

System.Windows.Data Error: 40 : BindingExpression path error: 'Some' property not found on 'object' ''NameOfDataBoundObject' (Name='')'. System.Windows.Data错误:40:BindingExpression路径错误:在“对象”“ NameOfDataBoundObject”(名称=“)”上找不到“某些”属性。 BindingExpression:Path=SomePath; BindingExpression:路径= SomePath; DataItem='NameOfDataBoundObject' (Name=''); DataItem ='NameOfDataBoundObject'(Name =''); target element is 'TypeOfUiElement' (Name='NameOfUiElement'); 目标元素是'TypeOfUiElement'(Name ='NameOfUiElement'); target property is 'PropertyName' (type 'TypeOfProperty') 目标属性是“ PropertyName”(类型“ TypeOfProperty”)

These are all valuable clues... pay attention to them, because they help you track down your problems. 这些都是有价值的线索...请注意它们,因为它们可以帮助您找到问题所在。

I added solution at the end of the question. 我在问题的末尾添加了解决方案。

Regards, Igor 问候,伊戈尔

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

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