【问题标题】:Databinding ObservableCollection<T> to Datagrid not working数据绑定 ObservableCollection<T> 到 Datagrid 不起作用
【发布时间】:2023-03-13 20:48:01
【问题描述】:

更新现在我想我已经缩小了问题的范围。 我创建了一个类

public class OptionStrike
{
    public OptionStrike(double p1, double p2, int p3)
    {
        // TODO: Complete member initialization
        P_OI = p1;
        StrikePrice = p2;
        P_Volume = p3;
    }

    public OptionStrike()
    {
        // TODO: Complete member initialization
    }

    public double P_OI { get; set; }
    public double P_Volume { get; set; }
    public double StrikePrice { get; set; }
}

现在,如果我将值加载到此 OptionStrike 为

private void Test(object obj)
{
    oOs = new ObservableCollection<OptionStrike>(new OptionStrike[]
    {
        new OptionStrike(4201, 7500.00, 12345),
        new OptionStrike(818859, 7500.00, 123),
        new OptionStrike(84545, 8000.00, 23645),
        new OptionStrike(8889955, 8000.00,99999)
    });
}

它显示在窗口的数据网格中,但如果我这样做:

    _oOC = new ObservableCollection<OptionStrike>();
    OptionStrike os = new OptionStrike();
    os.StrikePrice=7500;
    os.P_Volume=545;
    os.P_OI=45454;
    _oOC.Add(os);
    os.StrikePrice = 7600;
    os.P_Volume = 5566;
    os.P_OI = 45455;
    _oOC.Add(os);

数据网格是空白的..

字段 oOC 正在填充,我已经检查过了,但它仍然没有显示在 Datagrid 中...任何建议...

oOC 被声明为

private ObservableCollection<OptionStrike> _oOC;
public ObservableCollection<OptionStrike> oOC
{
    get { return _oOC; }
    set
    {
        if (value != _oOC)
        {
            _oOC = value;
            OnPropertyChanged(new PropertyChangedEventArgs("oOC"));
        }
    }
}

老问题我有一个 ObservableCollection 我正在尝试绑定到 DataGrid..

private ObservableCollection<Option> _optionChain = new ObservableCollection<Option>();
public ObservableCollection<Option> OptionChain
{
    get { return _optionChain; }
    set
    {
        if (value != _optionChain)
        {
            _optionChain = value;
            PropChanged("OptionChain");
        }
    }
}

我的 OptionChain 集合正在像

一样被填充
private void ProcessOptionsData()
{
    OptionChain = d.ProcessOptionChainData(OptionChainHtmlElement, Ticker, Expiry);
}

选项类有

public string type;             // option typ (put/call)
public string stock;            // option stock ticker
public string symbol;           // option symbol
public double strike;           // option strike price

XAML 是

<DataGrid ItemsSource="{Binding OptionChain}" AutoGenerateColumns="False" DataContext="{Binding Mode=Default}">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Type" Binding="{Binding type}" />
    <DataGridTextColumn Header="Strike" Binding="{Binding strike}" />
  </DataGrid.Columns>
</DataGrid>

现在数据网格没有被填充。我尝试了AutoGenerateColumn="True",但无济于事...还尝试了DataGridTextColumn绑定到Option.strike等等,但没有成功..

我哪里错了?

(我正在使用 ViewModelLocator)

编辑
现在我已经清除了所有内容。只有一个文本框和一个标签。当我在文本框中写东西时,它并没有反映在标签中。代码是

public class MainViewModel : INotifyPropertyChanged
    {
        #region Fields

        private string _ticker;
        public string Ticker
        {
            get { return _ticker; }
            set
            {
                if (value != _ticker)
                {
                    _ticker = value;
                    OnPropertyChanged("Ticker");
                }
            }
        }

        private string _status;
        public string Status
        {
            get { return _status;}
            set
            {
                if (value!=_status)
                {
                    _status = value;
                    OnPropertyChanged("Status");
                }
            }
        }

        public string PostBack
        {
            get { return string.Format("{0}, for expiry at ", Ticker); }
        }
        #endregion Fields

        public event PropertyChangedEventHandler PropertyChanged;
        // Create the OnPropertyChanged method to raise the event 
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

` MainWindow 的 XAML 就像

<Grid>
  <StackPanel Orientation="Horizontal">
    <TextBox Background="Transparent" Foreground="White" Text="{Binding Ticker}" HorizontalContentAlignment="Left" Width="150" VerticalContentAlignment="Center" Height="28" FontSize="18" Margin="10,0,0,0" />
    <Label Content="{Binding PostBack}" Width="250" Height="28" Margin="10,0,0,0" />
  </StackPanel>
</Grid>

MainWindow 的代码隐藏被用于数据上下文..

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        MainViewModel mvm = new MainViewModel();
        this.DataContext = mvm;
    }
}

【问题讨论】:

  • 它没有被填充 - 它正在被创建。 PropChanged 不能以相同的方式处理集合。如果你清除 OC 然后添加它应该工作的值。
  • 绑定工作正常吗?您正在将 DataContext 绑定到您自己的 DataContext,这看起来很奇怪而且没用......您确定这就是您想要实现的目标吗?
  • @almulo Yup 绑定工作正常,但我面临一个关于绑定的问题,我必须提及.. 编辑问题..
  • 你试过我的答案了吗?是还是不是?
  • 听起来您的DataGrid.DataContext 不正确。你能确认它是什么物体吗?您可以使用WPF Snoop 等第三方工具进行验证。 (另外@almulo 可能是正确的,您不需要DataContext="{Binding Mode=Default}"... XAML 的那一点毫无意义)

标签: c# wpf data-binding datagrid observablecollection


【解决方案1】:

NotifyPropertyChanged 与集合的工作方式不同

试试

private void ProcessOptionsData()
{   
    OptionChain.Clear();
    ForEach(Option opt in d.ProcessOptionChainData(OptionChainHtmlElement, Ticker, Expiry);
       OptionChain.Add(opt);
}

【讨论】:

  • 它应该只适用于NotifyPropertyChanged,无需逐项添加。
  • @almulo 但操作表示它不起作用。 NotifyPropertyChanged 与集合的工作方式不同。你投了我的票吗?
  • 不是反对者,但您的问题出现在低质量帖子审核队列中。更多解释会有所帮助。
【解决方案2】:

一个问题是您的 Option 类属性上没有 getter 或 setter。

应该是这样的:

public string type { get; set; }
public string stock { get; set; } 
public string symbol { get; set; }
public double strike { get; set; }

正如你所拥有的,它会导致绑定异常,因为找不到属性。

您在 XAML 中的 DataContext 可能错误 - 但这无法通过您提供的代码进行检查。

【讨论】:

  • 您是在问我是否可以发布您的完整代码?为什么不尝试给您的“选项”类属性获取/设置如图所示并报告回来......
  • 正如我所说,您的数据上下文很有可能是错误的 - 如果它是一个主窗口,请在 XAML 的窗口级别使其“自我”。下载snoopwpf.codeplex.com 以在运行时检查您的绑定。
  • 会这样做并报告...我正在尝试删除多余的代码,例如 viewmodellocator,因为我只有一个视图和 ViewModel.. 还创建了一个新的 List 以显示在 datagrid..在文本框中更改文本后,我仍然无法更新标签。它反映在视图模型中,因为我可以通过暂停执行看到它,但是 Propertychanged 事件没有显示响应,即使用该属性的地方不是更新了...
【解决方案3】:

使用提供的新代码,您似乎只需要为 PostBack 属性添加一个 PropertyChanged 通知。

由于该属性已计算,除非您通知它已更改,否则它不会自动重新计算。你应该在Ticker setter 中这样做,因为 PostBack 取决于它的值。像这样:

    private string _ticker;
    public string Ticker
    {
        get { return _ticker; }
        set
        {
            if (value != _ticker)
            {
                _ticker = value;
                OnPropertyChanged("Ticker");
                OnPropertyChanged("PostBack");
            }
        }
    }

这样,每次在 TextBox 上键入内容时,都会通知视图 PostBack 的值也发生了变化,并且它必须刷新 Label 的 Binding。

哦,顺便说一句,我认为 TextBox 的默认绑定将 UpdateSourceTrigger 设置为 LostFocus。如果您希望每次编写内容时都更新 Label 而不必等待离开 TextBox,您可能需要将其设置为 PropertyChanged(甚至使用 Delay 以获得更好的性能):

<TextBox Background="Transparent"
         Foreground="White"
         Text="{Binding Ticker, UpdateSourceTrigger=PropertyChanged, Delay=1000}"
         HorizontalContentAlignment="Left"
         Width="150"
         VerticalContentAlignment="Center"
         Height="28"
         FontSize="18"
         Margin="10,0,0,0" />

【讨论】:

  • 工作了,谢谢...现在回到 ObservableCollection 的 Datagrid 绑定...将在完全实现后恢复...
猜你喜欢
  • 2014-03-18
  • 2013-01-14
  • 1970-01-01
  • 2017-02-08
  • 2018-12-10
  • 2016-09-13
  • 2011-08-03
  • 2013-09-07
  • 2013-10-14
相关资源
最近更新 更多