C# WPF双向数据绑定列表框到WPF can中的模型';无法获取所选值

C# WPF双向数据绑定列表框到WPF can中的模型';无法获取所选值,c#,wpf,xaml,data-binding,listbox,C#,Wpf,Xaml,Data Binding,Listbox,我正在WPF中努力进行数据绑定,在搜索了各个方面后,我仍然看不到我缺少了什么,无法使用列表中的选定项更新模型。 我有两个实体,一个Slot和一个SlotType public class Slot : BindableObject, INotifyPropertyChanged { private int slotID; public int SlotID { get { return slotID; } set {

我正在WPF中努力进行数据绑定,在搜索了各个方面后,我仍然看不到我缺少了什么,无法使用列表中的选定项更新模型。 我有两个实体,一个Slot和一个SlotType

public class Slot : BindableObject, INotifyPropertyChanged
{
    private int slotID;
    public int SlotID
    {
        get { return slotID; }
        set
        {
            if (slotID != value)
            {
                slotID = value;
                RaisePropertyChanged("SlotID");
            }
        }
    }
    private string user;
    public string SlotUser
    {
        get { return user; }
        set
        {
            if (user != value)
            {
                user = value;
                RaisePropertyChanged("SlotUser");
            }
        }
    }

    private int slotUserID;
    public int SlotUserID
    {
        get { return slotUserID; }
        set
        {
            if (slotUserID != value)
            {
                slotUserID = value;
                RaisePropertyChanged("SlotUserID");
            }
        }
    }

    private int slotType;
    public int SlotType
    {
        get { return slotType; }
        set
        {
            if (slotType != value)
            {
                slotType = value;
                RaisePropertyChanged("SlotType");
            }
        }
    }

    private DateTime slotStartDateTime;
    public DateTime SlotStartDateTime
    {
        get { return slotStartDateTime; }
        set
        {
            if (slotStartDateTime != value)
            {
                slotStartDateTime = value;
                RaisePropertyChanged("SlotStartDateTime");
            }
        }
    }
public class SlotType : BindableObject, INotifyPropertyChanged
{
    private int slotTypeID;
    public int SlotTypeID
    {
        get { return slotTypeID; }
        set
        {
            if (slotTypeID != value)
            {
                slotTypeID = value;
                RaisePropertyChanged("SlotTypeID");
            }
        }
    }
    private string slotTypeDesc;
    public string SlotTypeDesc
    {
        get { return slotTypeDesc; }
        set
        {
            if (slotTypeDesc != value)
            {
                slotTypeDesc = value;
                RaisePropertyChanged("SlotTypeDesc");
            }
        }
    }
    public override string ToString()
    {
        return SlotTypeDesc;
    }
}
然后我创建了一个包含这两者的类,并将我的窗口上下文设置为这个类

public class SlotWithTypes 
{
    public ObservableCollection<SlotType> slotTypes { get; set; }
    public Slot slot { get; set; }
}
最后,在我的XAML中,我有了我的列表框

<Grid>
    <ListBox Name="lstSlotTypes" 
             HorizontalAlignment="Left" 
             Height="200" 
             Margin="0,10,0,0" 
             VerticalAlignment="Top" 
             Width="194"                 
             ItemsSource="{Binding slotTypes}" 
             SelectedItem="{Binding Path=slot.Type, Mode=TwoWay}"
             SelectedValue="{Binding slotTypes.SlotTypeID, Mode=TwoWay}" 
             SelectedValuePath="{Binding slot.Type, Mode=TwoWay}" 
             DisplayMemberPath="{Binding slotTypes.SlotTypeDesc}"                  
             SelectionChanged="lstSlotTypes_SelectionChanged">
    </ListBox>
    <TextBox HorizontalAlignment="Left" 
             Height="23" 
             Margin="10,246,0,0" 
             TextWrapping="Wrap" 
             Text="{Binding slot.SlotStartDateTime, Mode=TwoWay}" 
             VerticalAlignment="Top" 
             Width="74"/>
</Grid>

为了进行测试,我将一个绑定到slotstartdatetime的文本框放入其中,该文本框可以工作并更新回我的模型。我在listbox上尝试了多种绑定格式,可以获得要显示的SlotTypes列表,但无法使用所选值更新Slot实体


我意识到这已经成为一个很长的问题,但请如果有人能看到我做错了什么

我可以看出这里有很多错误,首先,这就是您的xaml如何完成这项工作:

    <ListBox Name="lstSlotTypes" HorizontalAlignment="Left" Height="200" Margin="0,10,0,0" VerticalAlignment="Top" Width="194"                 
        ItemsSource="{Binding slotTypes}" 
             SelectedValue="{Binding Path=slot.SlotType}"
             SelectedValuePath="SlotTypeID"
  DisplayMemberPath="SlotTypeDesc" >
    </ListBox>

现在,当您不知道哪些绑定不起作用时,在大多数情况下,这是由于输出窗口中可见的绑定错误造成的,这确实很有帮助,所以每次都要查看。例如,在xaml上,这就是输出窗口显示的内容:

System.Windows.Data错误:40:BindingExpression路径错误:“类型” 在“对象”“插槽”(HashCode=62085918)上找不到属性。 BindingExpression:Path=slot.Type;DataItem='SlotWithTypes' (HashCode=23184054);目标元素是“ListBox” (Name='lstSlotTypes');目标属性为“SelectedItem”(类型 “对象”)System.Windows.Data错误:40:BindingExpression路径 错误:“对象”上未找到“SlotTypeID”属性 ''ObservableCollection'1'(HashCode=58050239')。 BindingExpression:Path=slotTypes.SlotTypeID;DataItem='SlotWithTypes' (HashCode=23184054);目标元素是“ListBox” (Name='lstSlotTypes');目标属性为“SelectedValue”(类型 '对象')

如你所见,已经有了一些信息

现在,您的xaml有什么问题:

  • Slot
    类没有
    Type
    属性,只有
    SlotType
    属性
  • 您无法绑定到
    slot.SlotType
    SelectedItem
    ,因为
    SelectedItem
    保存了
    ItemsSource
    中的整个选定对象-在这种情况下,是
    SlotType
    类,而绑定属性
    slot.SlotType
    的类型是
    int
    。因此,在这种情况下,您需要使用
    SelectedValue
    属性,而不是
    SelectedItem
  • 看起来您将
    SelectedValue
    SelectedValuePath
    相混淆,
    SelectedValue
    绑定指向datacontext中存储所选项目值的对象,在这种情况下=
    slot.SlotType
  • SelectedValuePath-应将选定项上的路径设置为选定值-它是一个静态字符串,无需绑定任何内容
  • DisplayMemberPath-如上所述,它是一个静态字符串,指示持有需要显示的值的属性的路径-无需在此处绑定任何内容

代码有几个问题:

  • visual studio输出窗口中存在两个绑定错误(如果定义了列表框源并包含元素),原因是SelectedValuePath的绑定错误,源类型冲突。以下是对我有效的解决方案
  • 数据上下文收集初始化:

    private void InitDataContext()
    {
        DataContext = new SlotWithTypes
        {
            slot = new Slot(),
            slotTypes = new ObservableCollection<SlotType>(new List<SlotType>
            {
                new SlotType
                {
                    SlotTypeDesc = "Bla Bla 1",
                    SlotTypeID = 1,
                },
                new SlotType
                {
                    SlotTypeDesc = "Bla Bla 2",
                    SlotTypeID = 2,
                }
            })
        };
    }
    
    private void InitDataContext()
    {
    DataContext=新的SlotWithTypes
    {
    插槽=新插槽(),
    slotTypes=新的ObservableCollection(新列表
    {
    新SlotType
    {
    SlotTypeDesc=“Bla Bla 1”,
    SlotTypeID=1,
    },
    新SlotType
    {
    SlotTypeDesc=“Bla Bla 2”,
    SlotTypeID=2,
    }
    })
    };
    }
    
  • Xaml代码:

    <Grid>
    <ListBox Name="lstSlotTypes" HorizontalAlignment="Left" 
             Height="200" Margin="0,10,0,0" 
             VerticalAlignment="Top" Width="194" 
             ItemsSource="{Binding slotTypes}" 
             SelectedValue="{Binding SelectedSlotType, Mode=TwoWay}" 
             SelectedValuePath="SlotTypeID" DisplayMemberPath="SlotTypeDesc" 
             SelectionChanged="lstSlotTypes_SelectionChanged">
    </ListBox></Grid>
    
    
    
  • SlotWithTypes代码:

    public ObservableCollection<SlotType> slotTypes { get; set; }
    
    public Slot slot
    {
        get { return _slot; }
        set
        {
            _slot = value;
            OnPropertyChanged();
        }
    }
    
    public int SelectedSlotType
    {
        get { return _selectedSlotType; }
        set
        {
            _selectedSlotType = value;
            OnPropertyChanged();
            UpdateSlot(SelectedSlotType);
        }
    }
    
    private void UpdateSlot(int selectedSlotType)
    {
        slot.SlotType = selectedSlotType;
    }
    
    publicobservableCollection slotTypes{get;set;}
    公共插槽
    {
    获取{return\u slot;}
    设置
    {
    _槽=值;
    OnPropertyChanged();
    }
    }
    public int SelectedSlotType
    {
    获取{return\u selectedSlotType;}
    设置
    {
    _selectedSlotType=值;
    OnPropertyChanged();
    UpdateSlot(SelectedSlotType);
    }
    }
    私有void UpdateSlot(int-selectedSlotType)
    {
    slot.SlotType=selectedSlotType;
    }
    
  • 因此,每次我进行选择时,插槽的SlotType属性都将更改,并使用新值定义。在这里做你的逻辑


  • 关于,逻辑是什么?1.打开窗口时是否有项目列表?2.列表框中是否有任何项目?A您确定,在SelectedValuePath和DisplayMemberPath中需要绑定吗?:)这里一定有一些属性名称。非常感谢Alek,这是一个非常好的答案,有这么多信息。@user5466211只是为了好玩,看看这个。我希望它能帮你一点忙。@Noctis谢谢,非常有帮助,我已经搜索了很久,找不到像Alek的答案和你的文章那样有帮助的东西。@Golik谢谢你的努力,你是对的,我的xaml全错了
    public ObservableCollection<SlotType> slotTypes { get; set; }
    
    public Slot slot
    {
        get { return _slot; }
        set
        {
            _slot = value;
            OnPropertyChanged();
        }
    }
    
    public int SelectedSlotType
    {
        get { return _selectedSlotType; }
        set
        {
            _selectedSlotType = value;
            OnPropertyChanged();
            UpdateSlot(SelectedSlotType);
        }
    }
    
    private void UpdateSlot(int selectedSlotType)
    {
        slot.SlotType = selectedSlotType;
    }