我整天都在工作,但是我被困住了,没有解决方案。看起来很简单..
我有一个包含动态数量列的数据网格。每列都有一个带有CellTemplate和CellEditingTemplate的DataGridTemplateColumn。 CellEditingTemplate包含一个Combobox,其值为用户选择值后,CellTemplate中的TextBox必须更新为所选值。通常你会将它绑定到对象中的已知属性,但由于我不知道用户需要提前多少列,我必须在运行时创建这些属性(或其他东西)并尝试绑定此文本框和组合框到这个属性。我该如何解决这个问题?我更喜欢不使用ExpandoObjects而且我受限于.net 4.0
我的解决方案(尚未使用)是将wrapperobject添加到每个行对象的列表/数组中,然后在代码中生成一个新的DataGridTemplateColumn,其中组合框和文本框具有数组绑定到数组中的wrapperobject。在XAML中,这看起来像,但我不能将这0改为1,2,3,... 我可以在后面的代码中执行此操作,但我不知道如何将其绑定到WrapperObjectList [X] .Value?
这是一个简化的例子,希望有助于理解我想要实现的目标:
我有datagrid绑定到带有RowObjects [rowobject代表1行..;]的observablecollection。第一列是固定的,因此它绑定到RowObject中的属性。
现在我必须在此之后添加动态数量的列。这取决于用户选择了多少项(不在示例中,但您会明白这一点)。我点击按钮取代了这个动作。
对于每一列,我创建一个wrapperobject并将其添加到RowObject中的另一个observablecollection。这给了我一些灵活性,因为我事先不知道将添加多少列。这个Wrapperobject包含我需要显示的值。
此外,我需要将此WrapperObject绑定到我的组合框中的选区。因此,如果我编辑一行,我从组合框中选择一个值,然后必须在celltemplate的TextBox中显示(设置)所选的值。
示例代码:
代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadData();
this.DataContext = RowList;
}
private void LoadData()
{
RowList = new ObservableCollection<RowObject>();
WrapperObject lWrapperObject1 = new WrapperObject();
lWrapperObject1.Value = 1;
WrapperObject lWrapperObject2 = new WrapperObject();
lWrapperObject2.Value = 2;
WrapperObject lWrapperObject3 = new WrapperObject();
lWrapperObject3.Value = 3;
WrapperObject lWrapperObject4 = new WrapperObject();
lWrapperObject4.Value = 4;
WrapperObject lWrapperObject6 = new WrapperObject();
lWrapperObject6.Value = 6;
WrapperObject lWrapperObject8 = new WrapperObject();
lWrapperObject6.Value = 8;
RowObject lRowObject1 = new RowObject();
lRowObject1.RowObjectName = "RowObject1";
lRowObject1.WrapperCollection.Add(lWrapperObject1);
lRowObject1.WrapperCollection.Add(lWrapperObject2);
lRowObject1.WrapperCollection.Add(lWrapperObject6);
RowObject lRowObject2 = new RowObject();
lRowObject2.RowObjectName = "RowObject2";
lRowObject2.WrapperCollection.Add(lWrapperObject3);
lRowObject2.WrapperCollection.Add(lWrapperObject4);
lRowObject2.WrapperCollection.Add(lWrapperObject8);
RowList.Add(lRowObject1);
RowList.Add(lRowObject2);
}
public ObservableCollection<RowObject> RowList { get; set; }
private void Button_Click(object sender, RoutedEventArgs e)
{
DataGridTemplateColumn lTemplateColumn = new DataGridTemplateColumn();
lTemplateColumn.Header = "NewDynamicColumn";
var lMyCellTemplate= (DataTemplate)Resources["myCellTemplate"];
var lMyCellEditingTemplate = (DataTemplate)Resources["myCellEditingTemplate"];
// Text="{Binding WrapperCollection[1].Value}" ????
lTemplateColumn.CellTemplate =lMyCellTemplate;
lTemplateColumn.CellEditingTemplate = lMyCellEditingTemplate;
this.MyGrid.Columns.Add(lTemplateColumn);
}
}
public class RowObject : INotifyPropertyChanged
{
public RowObject()
{
WrapperCollection = new ObservableCollection<WrapperObject>();
ComboBoxList = new List<string>();
ComboBoxList.Add("10");
ComboBoxList.Add("20");
}
public ObservableCollection<WrapperObject> WrapperCollection { get; set; }
private string fRowObjectName;
public string RowObjectName
{
get { return fRowObjectName; }
set
{
fRowObjectName = value;
RaisePropertyChanged("RowObjectName");
}
}
public List<string> ComboBoxList { get; set; }
#region Notify property changed
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
public class WrapperObject : INotifyPropertyChanged
{
private int fValue;
public int Value
{
get {return fValue;}
set
{
fValue = value;
RaisePropertyChanged("Value");
}
}
#region Notify property changed
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
的Xaml:
<Window.Resources>
<DataTemplate x:Key="myCellTemplate">
<TextBlock Text="{Binding WrapperCollection[1].Value}" />
</DataTemplate>
<DataTemplate x:Key="myCellEditingTemplate">
<ComboBox ItemsSource="{Binding ComboBoxList}" />
</DataTemplate>
</Window.Resources>
<StackPanel>
<DataGrid x:Name="MyGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding RowObjectName}"/>
<DataGridTextColumn Header="ExampleColumn1" Binding="{Binding WrapperCollection[0].Value}"/>
<DataGridTemplateColumn Header="ExampleColumn2" CellTemplate="{StaticResource myCellTemplate}" CellEditingTemplate="{StaticResource myCellEditingTemplate}"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="Click" Click="Button_Click" Width="100" Margin="20"/>
</StackPanel>
ExampleColumn1和ExampleColumn2是此示例中唯一可编辑的列,单击该按钮后,添加的列也可以编辑。 现在我认为解决方案就像在后面的代码中创建一个新的绑定到WrapperCollection [2] .Value,WrapperCollection [3] .Value等,但是如何?
答案 0 :(得分:0)
XAMLReader救了我!现在我可以创建任何我想要的DataTemplate ..
public DataTemplate CreateDataTemplate(Type type, int aNumber)
{
StringReader stringReader = new StringReader(
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
<" + type.Name + @" Text=""{Binding WrapperCollection[" + aNumber.ToString() + @"].Value}""/>
</DataTemplate>");
XmlReader xmlReader = XmlReader.Create(stringReader);
return XamlReader.Load(xmlReader) as DataTemplate;
}
{
...
TextBlock textBlock = new TextBlock();
var lMyCellTemplate = CreateDataTemplate(textBlock.GetType(), Counter);
}