我已经玩了一段时间了,虽然我可以让我的设计时间数据正确绑定,但我似乎无法将运行时数据绑定。我花了很多时间在网上看了很多关于数据绑定方式的例子,但是没有遇到任何像这样做的事情。
我的想法是Window使用RelativeSource绑定到自身,然后允许我将网格绑定到Window的属性,即MyWidget。我想我已经用我的设计时间数据复制了这个,所以我不确定设计师的工作原理,但是当我运行它时,我只是得到一个空白的窗口......
这是我的XAML窗口:
<Window x:Class="XamlPrototype.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XamlPrototype"
mc:Ignorable="d"
Title="MainWindow" Height="646" Width="344"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DataContext="{Binding Source={d:DesignInstance Type=local:DesignTimeWidgetData, IsDesignTimeCreatable=True}}">
<Grid x:Name="MyGrid"
DataContext="{Binding MyWidget}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="20" />
<RowDefinition Height="10" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock FontSize="20" VerticalAlignment="Center" FontWeight="Medium" Grid.Row="0" Margin="20,20,0,0" Text="{Binding Title}" />
<TextBlock FontSize="12" VerticalAlignment="Top" Grid.Row="1" Margin="20,0,0,0" Text="{Binding Subtitle}" />
<StackPanel Grid.Row="3">
<ItemsControl
x:Name="ItemsControl"
ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<Rectangle Stroke="Red" StrokeThickness="5" Width="25" Height="25" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,0,0"></Rectangle>
<TextBlock FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,5" Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
..其代码背后:
public partial class MainWindow : Window
{
public Widget MyWidget { get; set; }
public MainWindow()
{
InitializeComponent();
InitializeWidgetData();
}
private void InitializeWidgetData()
{
MyWidget = new Widget
{
Title = "This is the Title",
Subtitle = "This is the subtitle",
Items = new List<string>
{
"Item Short Name 1",
"Item Short Name 2",
"Item Short Name 3",
"Item Short Name 4",
"Item Short Name 5",
"Item Short Name 6",
"Item Short Name 7",
"Item Short Name 8"
}
};
}
}
数据上下文:
public class Widget
{
public string Title { get; set; }
public string Subtitle { get; set; }
public List<string> Items { get; set; }
}
和我的设计时间数据:
public class DesignTimeWidgetData
{
public Widget MyWidget { get; set; }
public DesignTimeWidgetData()
{
MyWidget = new Widget
{
Title = "Design Time Title",
Subtitle = "Design Time Subtitle",
Items = new List<string>
{
"Design Time Short Name 1",
"Design Time Short Name 2",
"Design Time Short Name 3",
"Design Time Short Name 4",
"Design Time Short Name 5",
"Design Time Short Name 6",
"Design Time Short Name 7",
"Design Time Short Name 8"
}
};
}
}
更新
按照HighCore的建议和示例,以及一些额外的谷歌搜索,我修改了项目如下:
App XAML:
<Application x:Class="XamlPrototype.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:XamlPrototype"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:WindowViewModel x:Key="WindowViewModel" />
</Application.Resources>
Window XAML:
<Window x:Class="XamlPrototype.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XamlPrototype"
mc:Ignorable="d"
Title="MainWindow" Height="646" Width="344"
DataContext="{StaticResource WindowViewModel}"
d:DataContext="{Binding Source={d:DesignInstance Type=local:DesignTimeViewModel, IsDesignTimeCreatable=True}}">
<Grid x:Name="MyGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="20" />
<RowDefinition Height="10" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock FontSize="20" VerticalAlignment="Center" FontWeight="Medium" Grid.Row="0" Margin="20,20,0,0" Text="{Binding WindowTitle}" />
<TextBlock FontSize="12" VerticalAlignment="Top" Grid.Row="1" Margin="20,0,0,0" Text="{Binding WindowSubtitle}" />
<StackPanel Grid.Row="3">
<ItemsControl
x:Name="ItemsControl"
ItemsSource="{Binding WindowItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<Rectangle Stroke="Red" StrokeThickness="5" Width="25" Height="25" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,0,0"></Rectangle>
<TextBlock FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,5" Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
..及其背后的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
ViewModel:
public class WindowViewModel : INotifyPropertyChanged
{
private Widget _widget;
public string WindowTitle
{
get { return _widget.Title ?? "Error!"; }
}
public string WindowSubtitle
{
get { return _widget.Subtitle ?? "Error!"; }
}
public List<string> WindowItems
{
get { return _widget.Items ?? new List<string>(); }
}
public WindowViewModel()
{
//in reality this would come from the Db, or a service perhaps..
_widget = new Widget
{
Title = "This is the Title",
Subtitle = "This is the subtitle",
Items = new List<string>
{
"Item Short Name 1",
"Item Short Name 2",
"Item Short Name 3",
"Item Short Name 4",
"Item Short Name 5",
"Item Short Name 6",
"Item Short Name 7",
"Item Short Name 8"
}
};
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
// take a copy to prevent thread issues
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
设计时(viewmodel)数据:
public class DesignTimeViewModel
{
public string WindowTitle { get; set; }
public string WindowSubtitle { get; set; }
public List<string> WindowItems { get; set; }
public DesignTimeViewModel()
{
var widget = new Widget
{
Title = "Design Time Title",
Subtitle = "Design Time Subtitle",
Items = new List<string>
{
"Design Time Short Name 1",
"Design Time Short Name 2",
"Design Time Short Name 3",
"Design Time Short Name 4",
"Design Time Short Name 5",
"Design Time Short Name 6",
"Design Time Short Name 7",
"Design Time Short Name 8"
}
};
WindowTitle = widget.Title;
WindowSubtitle = widget.Subtitle;
WindowItems = widget.Items;
}
}
小部件数据保持不变。
答案 0 :(得分:2)
快速解决方案:
在构造函数中交换这些行的顺序:
public MainWindow()
{
InitializeWidgetData(); // This first
InitializeComponent(); // This second
}
真正的解决方案:
创建一个正确的ViewModel,它实现INotifyPropertyChanged
绑定到,而不是将窗口绑定到自身。