数据绑定 ObservableCollection<T> 到 Datagrid 不工作
Databinding ObservableCollection<T> to Datagrid not working
更新 现在我想我已经缩小了问题范围。
我创建了一个 class
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)
});
}
它显示在 window 的数据网格中,但如果我这样做:
_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);
}
选项 Class 有
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;
}
}
NotifyPropertyChanged 与集合的工作方式不同
尝试
private void ProcessOptionsData()
{
OptionChain.Clear();
ForEach(Option opt in d.ProcessOptionChainData(OptionChainHtmlElement, Ticker, Expiry);
OptionChain.Add(opt);
}
一个问题是您的 Option class 属性上没有 getter 或 setter。
它应该是这样的:
public string type { get; set; }
public string stock { get; set; }
public string symbol { get; set; }
public double strike { get; set; }
如您所见,它会导致绑定异常,因为找不到属性。
您在 XAML 中的 DataContext 也可能 是错误的 - 但这无法通过您提供的代码进行检查。
使用提供的新代码,您似乎只需要为 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 的值也已更改,并且它必须刷新标签的绑定。
哦,顺便说一下,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" />
更新 现在我想我已经缩小了问题范围。 我创建了一个 class
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; }
}
现在,如果我将值作为
加载到此 OptionStrikeprivate 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)
});
}
它显示在 window 的数据网格中,但如果我这样做:
_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);
}
选项 Class 有
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;
}
}
NotifyPropertyChanged 与集合的工作方式不同
尝试
private void ProcessOptionsData()
{
OptionChain.Clear();
ForEach(Option opt in d.ProcessOptionChainData(OptionChainHtmlElement, Ticker, Expiry);
OptionChain.Add(opt);
}
一个问题是您的 Option class 属性上没有 getter 或 setter。
它应该是这样的:
public string type { get; set; }
public string stock { get; set; }
public string symbol { get; set; }
public double strike { get; set; }
如您所见,它会导致绑定异常,因为找不到属性。
您在 XAML 中的 DataContext 也可能 是错误的 - 但这无法通过您提供的代码进行检查。
使用提供的新代码,您似乎只需要为 PostBack
属性.
由于计算了 属性,除非您通知它已更改,否则它不会自动重新计算。您应该在 Ticker
setter 中这样做,因为 PostBack 取决于它的值。像这样:
private string _ticker;
public string Ticker
{
get { return _ticker; }
set
{
if (value != _ticker)
{
_ticker = value;
OnPropertyChanged("Ticker");
OnPropertyChanged("PostBack");
}
}
}
这样,每次在 TextBox 上键入内容时,您都会通知视图 PostBack 的值也已更改,并且它必须刷新标签的绑定。
哦,顺便说一下,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" />