wpf ListItem SelectedValue对象始终为null

时间:2017-06-29 08:28:15

标签: wpf listbox

我有一个简单的ListBox和一个TextBox,我希望在文本框中显示Listbox的selectedvalue属性,但我的ViewModel的选定对象始终为null。 我在这里缺少什么?

我的XAML

<StackPanel>
    <Canvas>
        <TextBox x:Name="TxtMail" Width="244" FontSize="14" Canvas.Left="36" Canvas.Top="34" Height="20" Text="{Binding CurrentRec.Name,Mode=OneWay}" />
        <ListBox x:Name="AllMatching" Width="{Binding ElementName=TxtMail,Path=Width}" Height="100" Canvas.Top="54" Canvas.Left="36"  DisplayMemberPath="Name" SelectedItem="{Binding CurrentRec,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedValue="Name" SelectedValuePath="Name" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" />
        <Button Content="Test" x:Name="cmdtest" Click="cmdtest_Click"/>
    </Canvas>

我的ViewModel:

public class VM_Data : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public int p_ID;
    public double p_SP, p_CP;
    public string p_Name;
    public List<DM_Data> AllData;

    public DM_Data CurrentRec;
    public VM_Data()
    {
        LoadData();
    }
    public int ID
    {
        get { return p_ID; }
        set
        {
            if (p_ID != value)
            {
                RaisePropertyChangedEvent("ID");
                p_ID = value;
            }
        }
    }

    public double SP
    {

        get { return p_SP; }
        set
        {
            if (p_SP != value)
            {
                RaisePropertyChangedEvent("SP");
                p_SP = value;
            }
        }
    }
    public double CP
    {
        get { return p_CP; }
        set
        {
            if (p_CP != value)
            {
                RaisePropertyChangedEvent("CP");
                p_CP = value;
            }
        }
    }

    public string Name
    {
        get { return p_Name; }
        set
        {
            if (p_Name != value)
            {
                RaisePropertyChangedEvent("Name");
                p_Name = value;
            }
        }
    }
    private void LoadData()
    {
        AllData = new List<DM_Data>();
        string[] strNames = "Jatinder;Shashvat;shashikala;shamsher;shahid;justin;jatin;jolly;ajay;ahan;vijay;suresh;namita;nisha;negar;zenith;zan;zen;zutshi;harish;hercules;harman;ramesh;shashank;mandeep;aman;amandeep;amarjit;asim;akshay;amol;ritesh;ritivik;riz;samana;samaira;bhagwandass;bhagwan;bhawna;bhavna".Split(';');
        for(int i=0;i<=strNames.GetUpperBound(0);i++)
        {
            DM_Data NewRec = new DM_Data();
            NewRec.CP = new Random().Next(200, 400);
            NewRec.SP = new Random().Next(1, 10);
            NewRec.ID = i + 1;
            NewRec.Name = strNames[i];
            AllData.Add(NewRec);
        }
        AllData = AllData.OrderBy(item => item.Name).ToList();
    }
    private void RaisePropertyChangedEvent(string Property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(Property));
        }
    }
}

我的DataModel

public class DM_Data
{
    public int p_ID;
    public double p_SP, p_CP;
    public string p_Name;

    public int ID
    {
        get { return p_ID; }
        set { p_ID = value; }
    }

    public double SP
    {
        get { return p_SP; }
        set { p_SP = value; }
    }
    public double CP
    {
        get { return p_CP; }
        set { p_CP = value; }
    }

    public string Name
    {
        get { return p_Name; }
        set { p_Name = value; }
    }

MainWindow.Xaml.cs

public partial class MainWindow : Window
{
    VM_Data ViewModel;
    public MainWindow()
    {
        InitializeComponent();
         ViewModel = new VM_Data();
        this.DataContext = ViewModel;
        AllMatching.ItemsSource = ViewModel.AllData;
    }

    private void cmdtest_Click(object sender, RoutedEventArgs e)
    {
        DM_Data crec = ViewModel.CurrentRec;
    }
}

3 个答案:

答案 0 :(得分:1)

CurrentRec必须是提升PropertyChanged事件的属性

private DM_Data _currentRec;
public DM_Data CurrentRec
{
    get { return _currentRec; }
    set { _currentRec = value; RaisePropertyChangedEvent("CurrentRec"); }
}

在您发布的代码中,它是field,您无法绑定到字段:

public DM_Data CurrentRec;

答案 1 :(得分:0)

您无法绑定到字段! CurrentRec必须是属性。现在它是一个领域。

  1. 为什么要在代码隐藏中设置ItemsSource?在XAML中设置它。
  2. 您应该在之后致电RaisePropertyChangedEvent ,而不是之前更改了支持字段。
  3. 事件提升的模式不正确:if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(Property)); }您需要先将事件委托保存到变量或使用?.Invoke

  4. 不要在每次循环迭代时创建Random的新实例,因为您将得到相等的值。创建循环外的唯一一个并使用它。

答案 2 :(得分:0)

你在做什么有点MVVM,但不是真的。

无论如何,这是一个快速修复:

请查看Bindings

    <StackPanel>
        <Canvas>
            <TextBox x:Name="TxtMail" Width="244" FontSize="14" Canvas.Left="36" Canvas.Top="34" Height="20" Text="{Binding ElementName=AllMatching, Path=SelectedItem.Name}" />
            <ListBox x:Name="AllMatching" 
                     Width="{Binding ElementName=TxtMail,Path=Width}" 
                     Height="100" 
                     Canvas.Top="54" 
                     Canvas.Left="36"  
                     DisplayMemberPath="Name" 
                     SelectedItem="{Binding CurrentRec,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                     ScrollViewer.VerticalScrollBarVisibility="Auto" 
                     ScrollViewer.HorizontalScrollBarVisibility="Auto" />
            <Button Content="Test" x:Name="cmdtest" Click="cmdtest_Click"/>
        </Canvas>
    </StackPanel>

我认为你的想法是:Text="{Binding ElementName=AllMatching, Path=SelectedItem.Name}"

有条件的信息

<强>首先: 你向早期的家伙开火。请先分配值,然后再将其更改。

       if (p_Name != value)
        {
            RaisePropertyChangedEvent("Name");
            p_Name = value;
        }

<强>第二 使用ObservableCollection<DM_Data>ListBox了解更改。

<强>第三 使用Binding

的可能性

删除AllMatching.ItemsSource = ViewModel.AllData;并转到

        <ListBox x:Name="AllMatching"
                 ItemsSource="{Binding Path=AllData}"
                 ...
                 />

在完成所有这些之后 - 请男士查看一些教程。还要将您的代码从VM_Data重构为DataViewModel谢谢先生。