我有一个空的数据网格绑定到自定义对象的可观察集合。当我尝试通过 UI 创建一个新行时,我得到一个新行,但它似乎永远不会提交新行,除非我有另一个 UI 控件可以关注。如果没有其他控件,我只能通过新行的每一列进行选项卡,这是一个无限循环。如果我将 Textblock 更改为文本框,那么我可以在文本框上使用标签并获得新行。
下面是我的所有代码和 XAML。
XAML:
<Window x:Class="WPFDatagridTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<CollectionViewSource x:Name="MultiplierCollection" x:Key="MultiplierCollection"></CollectionViewSource>
</Window.Resources>
<Grid>
<DockPanel LastChildFill="True">
<TextBlock Name="NumberTotal" DockPanel.Dock="Bottom">test</TextBlock>
<DataGrid Name="TestGrid"
CanUserAddRows="True"
AutoGenerateColumns="False"
CanUserDeleteRows="True"
CanUserReorderColumns="False"
ItemsSource="{Binding Source={StaticResource MultiplierCollection}}" IsSynchronizedWithCurrentItem="True" AlternatingRowBackground="#FFF7EF9E" AlternationCount="1" SelectionUnit="CellOrRowHeader" ClipboardCopyMode="IncludeHeader">
<DataGrid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding BaseNumber,ValidatesOnDataErrors=True,ValidatesOnExceptions=True, Mode=TwoWay,NotifyOnSourceUpdated=true, UpdateSourceTrigger=LostFocus}" Header="Base Number"></DataGridTextColumn>
<DataGridTextColumn EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding Multiplier,ValidatesOnDataErrors=True,ValidatesOnExceptions=True, Mode=TwoWay,NotifyOnSourceUpdated=true,UpdateSourceTrigger=LostFocus}" Header="Multiplier"></DataGridTextColumn>
<DataGridTextColumn EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding Result,ValidatesOnDataErrors=True,ValidatesOnExceptions=True, Mode=OneWay,NotifyOnSourceUpdated=true,UpdateSourceTrigger=LostFocus}" Header="Result"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Grid>
</Window>
代码隐藏:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPFDatagridTesting.CustomObjects;
namespace WPFDatagridTesting
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
MultiplierObservableCollection mycollection = new MultiplierObservableCollection();
System.Windows.Data.CollectionViewSource MultiplierCollection;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
mycollection = new MultiplierObservableCollection();
mycollection.TotalResultsChanged +=mycollection_TotalResultsChanged;
MultiplierCollection = ((System.Windows.Data.CollectionViewSource)(this.FindResource("MultiplierCollection")));
MultiplierCollection.Source = mycollection.MultiplierClassList;
}
catch (Exception)
{
throw;
}
}
void mycollection_TotalResultsChanged(object sender, MultiplierCollectionResultsChangedEventArgs e)
{
this.NumberTotal.Text = e.MultiplierResults.ToString();
}
}
}
自定义对象:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace WPFDatagridTesting.CustomObjects
{
class MultiplierClass : INotifyPropertyChanged
{
protected virtual void Changed(string PropertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(PropertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public MultiplierClass()
{
}
private int _BaseNumber;
public int BaseNumber
{
get
{
return _BaseNumber;
}
set
{
if (_BaseNumber != value)
{
_BaseNumber = value;
Changed("BaseNumber");
Changed("Result");
}
}
}
private int _Multiplier;
public int Multiplier
{
get
{
return _Multiplier;
}
set
{
if (_Multiplier != value)
{
_Multiplier = value;
Changed("Multiplier");
Changed("Result");
}
}
}
public int Result
{
get
{
return _BaseNumber * _Multiplier;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace WPFDatagridTesting.CustomObjects
{
class MultiplierObservableCollection : ObservableCollection<MultiplierClass>
{
public ObservableCollection<MultiplierClass> MultiplierClassList { get; set; }
public MultiplierObservableCollection() : base()
{
MultiplierClassList = new ObservableCollection<MultiplierClass>();
MultiplierClassList.CollectionChanged += MultiplierClassList_CollectionChanged;
}
void MultiplierClassList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (MultiplierClass item in e.NewItems)
{
//Added items
item.PropertyChanged += myNewClass_PropertyChanged;
}
}
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
MultiplierClass myNewClass = new MultiplierClass();
myNewClass.PropertyChanged -= myNewClass_PropertyChanged;
}
myNewClass_PropertyChanged(this, null);
}
void myNewClass_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
MultiplierCollectionResultsChangedEventArgs myEventArgs = new MultiplierCollectionResultsChangedEventArgs();
myEventArgs.MultiplierResults = this.MultiplierClassList.Sum(mc => mc.Result);
EventHandler<MultiplierCollectionResultsChangedEventArgs> handler = TotalResultsChanged;
if (handler != null)
{
handler(this, myEventArgs);
}
}
public event EventHandler<MultiplierCollectionResultsChangedEventArgs> TotalResultsChanged;
}
public class MultiplierCollectionResultsChangedEventArgs : EventArgs
{
public int MultiplierResults { get; set; }
}
}