【问题标题】:WPF XAML Data BindingWPF XAML 数据绑定
【发布时间】:2015-11-23 05:59:25
【问题描述】:

我已经玩了一段时间了,虽然我可以让我的设计时数据正确绑定,但我似乎无法让运行时数据绑定。我花了很长时间在网上查看大量示例以了解各种数据绑定方式,但没有遇到任何这样做的人。

我的想法是 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 的建议和示例,以及我额外的谷歌搜索,我将项目修改如下:

应用 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>

窗口 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();
    }
}

视图模型:

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;
    }
}

小部件数据保持不变。

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    快速解决方案:

    在构造函数中交换这些行的顺序:

    public MainWindow()
    {
        InitializeWidgetData(); // This first
        InitializeComponent();  // This second
    }
    

    真正的解决方案:

    创建一个适当的 ViewModel 来实现 INotifyPropertyChanged 进行绑定,而不是将窗口绑定到自身。

    【讨论】:

    • 你能举一个你真正的解决方案的例子吗?
    猜你喜欢
    • 1970-01-01
    • 2011-08-15
    • 2011-07-15
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    相关资源
    最近更新 更多