问题
I am trying to run (in C# 4.0, Visual Studio 2010) the code from
- Unable to display a List as one of the columns of my view with ItemsControl and StackPanel?
having added instantiation of myOrders in MainWindow.xaml.cs of VS2010 WPF application project but am getting in XAML
Cannot resolve symbol 'myOrders' due to unknown data context
upon pointing in MainWindows.xaml a mouse on myOrders in line:
ItemsSource="{Binding myOrders}"
What would be the full XAML script for launching the WPF app in this case?
Update:
I removed my code since it is redundant to provided answers and comments.
Just to note that I was interested in the simplest kick-off illustration-realization of databinding of:
- compound (hierarchical or multidimensional/jagged arrays or lists) List<> objects (instantiated in C# but not in XAML)
- imitating kind of Master-Detail relationship, TreeView
which I could not find ready in the internet.
The code in tutorials, walkthroughs or examples, I could find, either do not compile or over-bloated by complications blurring the concepts and respectively comprehension.
I.e. I prefer the disappeared answer with simpler code, though I cannot upvote or mark it as correct, since it is not mine.
回答1:
First of all myOrders has to be a public property. it cannot be seen even if it's a public variable, secondly to make the view(XAML) aware of what's going in the code behind you need to set DataContext = this;
in the window's constructor
Set a property like this : public List<Order> myOrder {get;set;}
If you need to update the view from code behind then you need to implement INotifyPropertyChanged
interface. it's responsible of doing update view job. Here is a small tutorial from MSDN.
Last thing, (From my experience) you should go with a property of type ObservableCollection<Order>
instead of List<Order>
.
XAML :
<Grid>
<ItemsControl x:Name="visual"
ItemsSource="{Binding MyOrders}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<ItemsControl.ItemTemplate>
<!-- This defines the DataTemplate to display one Order object-->
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding OrderName}"
Margin="10" />
<ItemsControl ItemsSource="{Binding PartsList}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<ItemsControl.ItemTemplate>
<!-- This defines the DataTemplate to display one Parts object-->
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding PartName}"
TextAlignment="Center" />
<TextBlock Grid.Column="1"
Text="{Binding PartQuantity}"
TextAlignment="Center" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Code behind :
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public ObservableCollection<Order> MyOrders
{
get { return _myOrders; }
set { _myOrders = value; OnPropertyChanged("MyOrders"); }
}
Order order1 = new Order
{
OrderName = "Order1",
PartsList = new List<Parts>()
{
new Parts {PartName = "Part11", PartQuantity = 11},
new Parts {PartName = "Part12", PartQuantity = 12}
}
};
private ObservableCollection<Order> _myOrders;
public MainWindow()
{
InitializeComponent();
MyOrders = new ObservableCollection<Order>();
MyOrders.Add(order1);
DataContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Order
{
public string OrderName { get; set; }
public List<Parts> PartsList { get; set; }
}
public class Parts
{
public string PartName { get; set; }
public double PartQuantity { get; set; }
}
}
回答2:
The simpler answer:
This is funny but I do not see in HichemC's answer edits his penultimate edition of C# code working with the same XAML without any bloating by:
- ObservableCollection
- OnPropertyChanged()
- INotifyPropertyChanged
- PropertyChangedEventHandler
That this, simpler, code works for me:
public partial class MainWindow : Window
{
public List<Order> myOrders { get; set; }
Order order1 = new Order
{
OrderName = "Order1",
PartsList = new List<Parts>()
{
new Parts {PartName = "Part11", PartQuantity = 11},
new Parts {PartName = "Part12", PartQuantity = 12}
}
};
Order order2 = new Order
{
OrderName = "Order2",
PartsList = new List<Parts>()
{
new Parts {PartName = "Part21", PartQuantity = 21},
new Parts {PartName = "Part22", PartQuantity = 22},
new Parts {PartName = "Part23", PartQuantity = 23}
}
};
public MainWindow()
{
InitializeComponent();
myOrders = new List<Order>();
myOrders.Add(order1);
myOrders.Add(order2);
DataContext = this;
}
}
public class Order
{
public string OrderName { get; set; }
public List<Parts> PartsList { get; set; }
}
public class Parts
{
public string PartName { get; set; }
public double PartQuantity { get; set; }
}
}
来源:https://stackoverflow.com/questions/14473749/how-to-launch-the-simplest-code-illustrating-master-detail-compound-list-objec