【问题标题】:WPF Unexpected behavior binding ObservableCollection to UserControlWPF 将 ObservableCollection 绑定到 UserControl 的意外行为
【发布时间】:2015-09-16 15:24:24
【问题描述】:

我正在尝试将一堆用户控件绑定到 WPF 应用程序。这个想法是视图模型保存服务器名称列表,将它们传递给ObservableCollection,然后将集合绑定到主窗口。

在设计模式下,一切正常!但是,当我运行应用程序时,绑定似乎崩溃了,我不知道为什么。

这是用户控件的 XAML:

<UserControl x:Class="ServerMonitor.Wpf.ServerControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ServerMonitor.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.DataContext>
        <local:Server />
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.Resources>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="TextAlignment" Value="Center" />
                <Setter Property="HorizontalAlignment" Value="Stretch" />
            </Style>
        </Grid.Resources>

        <TextBlock Grid.Row="0" Text="{Binding Name}" />

        <TextBlock Grid.Row="8" Text="{Binding LastPolled}" />
    </Grid>
</UserControl>

这是视图模型(ViewModelBase 是实现 INotifyPropertyChanged 的​​抽象类):

public class MainWindowViewModel : ViewModelBase {

    private List<string> _MachineNames = new List<string> {
        "wschampad",
        // Test
        "T009", "T010", "T011", "T012",
    };
    public List<string> MachineNames {
        get { return _MachineNames; }
        set { _MachineNames = value; OnPropertyChanged("ManchineNames"); }
    }

    private ObservableCollection<Server> _Servers;
    public ObservableCollection<Server> Servers {
        get {
            if (_Servers == null) {
                _Servers = new ObservableCollection<Server>();
                foreach (var machine in MachineNames) {
                    _Servers.Add(new Server {
                        Name = machine, 
                        LastPolled = DateTime.Now, 
                    });
                }
                OnPropertyChanged("Servers");
            }

            return _Servers;
        }
        set { _Servers = value; OnPropertyChanged("Servers"); }
    }
}

这是 XAML 的主窗口:

<Window x:Class="ServerMonitor.Wpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ServerMonitor.Wpf"
        Title="Leading Hedge Server Monitor" Height="350" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Menu Grid.Row="0">
            <MenuItem Header="_File">
                <MenuItem Header="_Exit" Name="MenuFileExit" Click="MenuFileExit_Click" />

            </MenuItem>
            <MenuItem Header="_Edit">
                <MenuItem Header="_Options" Name="MenuEditOptions" IsEnabled="False" />
            </MenuItem>
            <MenuItem Header="_Help">
                <MenuItem Header="_About" Name="MenuHelpAbout" IsEnabled="False" />
            </MenuItem>
        </Menu>

        <ItemsControl Grid.Row="1" ItemsSource="{Binding Servers}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5">
                        <local:ServerControl DataContext="{Binding}" />
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

    </Grid>
</Window>

编辑

将 UserControl 中的 DataContext 更改为 ignorable 可以解决问题!

<UserControl x:Class="ServerMonitor.Wpf.ServerControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ServerMonitor.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <d:UserControl.DataContext>
        <local:Server />
    </d:UserControl.DataContext>

【问题讨论】:

    标签: c# wpf xaml data-binding


    【解决方案1】:

    在你的 UserControl 中去掉这个:

    <UserControl.DataContext>
        <local:Server />
    </UserControl.DataContext>
    

    这将覆盖您从ItemTemplate 传递给它的DataContext,并最终得到DateTimestring 的默认值。

    【讨论】:

    • 成功了!然而,我稍微调整了一下,这样我就可以保留智能感知。
    • 是的,我要补充一点,如果你说你仍然需要 IntelliSense 帮助:)
    • 感谢您的帮助。我从来没有想过控件的绑定会优先。
    • 爱 Live Netscape!
    猜你喜欢
    • 2014-05-03
    • 2010-12-07
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多