用户控件未更新某些属性

时间:2018-06-20 13:30:15

标签: c# wpf data-binding

我有一个名为MyItem的类,该类具有ID属性以及三个随机数属性。我有一个名为MyItemControl的UserControl,旨在显示MyItem的ID,三个随机数以及这三个随机数的总和。我在ListBox中显示MyItems的集合,并且我有一个contentcontrol,它通过MyItemControl UserControl显示有关ListBox所选MyItem的更多详细信息。

但是,我遇到一个问题,当选择MyItem时,contentcontrol仅更新ID和随机数,而不更新总和。我的猜测是因为Sum属性是在将MyItem绑定到MyItemControl之前计算的。我尝试过在设置MyItem属性时更改属性,但这似乎也不起作用。

在xaml中绑定MyItem属性后,如何更新Sum属性?

MyItem类:

public class MyItem
{
    private static Random random = new Random();

    public MyItem(string ID)
    {
        this.ID = ID;
        Num1 = random.Next();
        Num2 = random.Next();
        Num3 = random.Next();
    }

    public string ID { get; private set; }

    public int Num1 { get; private set; }

    public int Num2 { get; private set; }

    public int Num3 { get; private set; }

    public override string ToString()
    {
        return ID;
    }
}

MyItemControl xaml:

<UserControl x:Name="userControl" x:Class="testApp2.MyItemControl"
             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:testApp2"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel Margin="0">
        <StackPanel Margin="0" Orientation="Horizontal">
            <Label Content="ID:" Margin="0" HorizontalAlignment="Left"/>
            <Label Content="{Binding MyItem.ID, ElementName=userControl, Mode=OneWay}" Margin="0" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Margin="0" Orientation="Horizontal">
            <Label Content="Num1:" Margin="0" HorizontalAlignment="Left"/>
            <Label Content="{Binding MyItem.Num1, ElementName=userControl, Mode=OneWay}" Margin="0" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Margin="0" Orientation="Horizontal">
            <Label Content="Num2:" Margin="0" HorizontalAlignment="Left"/>
            <Label Content="{Binding MyItem.Num2, ElementName=userControl, Mode=OneWay}" Margin="0" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Margin="0" Orientation="Horizontal">
            <Label Content="Num3:" Margin="0" HorizontalAlignment="Left"/>
            <Label Content="{Binding MyItem.Num3, ElementName=userControl, Mode=OneWay}" Margin="0" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Margin="0" Orientation="Horizontal">
            <Label Content="Sum:" Margin="0" HorizontalAlignment="Left"/>
            <Label Content="{Binding Sum, ElementName=userControl, Mode=OneWay}" Margin="0" HorizontalAlignment="Left"/>
        </StackPanel>
    </StackPanel>
</UserControl>

MyItemControl的代码隐藏:

public partial class MyItemControl : UserControl, INotifyPropertyChanged
{
    public MyItemControl()
    {
        InitializeComponent();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }

    public MyItem MyItem
    {
        get { return (MyItem)GetValue(MyItemProperty); }
        set
        {
            SetValue(MyItemProperty, value);
            RaisePropertyChanged("MyItem");
            RaisePropertyChanged("Sum");
        }
    }

    public static readonly DependencyProperty MyItemProperty =
        DependencyProperty.Register("MyItem", typeof(MyItem), typeof(MyItemControl), new PropertyMetadata(null));


    public int Sum => MyItem != null ? MyItem.Num1 + MyItem.Num2 + MyItem.Num3 : 0;
}

MainWindow xaml:

<Window x:Name="window" x:Class="testApp2.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:testApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid Margin="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox Margin="5" SelectionChanged="ItemSelectionChanged" ItemsSource="{Binding MyItems, ElementName=window}"/>
        <ContentControl Content="{Binding Selection, ElementName=window, Mode=OneWay}" Grid.Column="1" Margin="5">
            <ContentControl.ContentTemplate>
                <DataTemplate DataType="{x:Type local:MyItem}">
                    <local:MyItemControl MyItem="{Binding}"/>
                </DataTemplate>
            </ContentControl.ContentTemplate>
        </ContentControl>
    </Grid>
</Window>

MainWindow背后的代码:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        MyItems = new ObservableCollection<MyItem>
        {
            new MyItem("Boop"),
            new MyItem("Bop"),
            new MyItem("Beep")
        };
        InitializeComponent();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }

    public ObservableCollection<MyItem> MyItems { get; private set; }

    private MyItem selection = null;
    public MyItem Selection
    {
        get { return selection; }
        set
        {
            selection = value;
            RaisePropertyChanged("Selection");
        }
    }

    private void ItemSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ListBox listbox = (ListBox)sender;
        if (listbox.SelectedIndex > -1)
        {
            Selection = (MyItem)listbox.SelectedItem;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

来自Clemens的建议。我删除了INotifyPropertyChanged接口,并将PropertyChangedCallback与MyItem属性一起使用,该属性重新计算了Sum属性。这似乎工作正常。

更新的MyItemControl:

public partial class MyItemControl : UserControl
{
    public MyItemControl()
    {
        InitializeComponent();
        Sum = MyItem != null ? MyItem.Num1 + MyItem.Num2 + MyItem.Num3 : 0;
    }

    public MyItem MyItem
    {
        get { return (MyItem)GetValue(MyItemProperty); }
        set { SetValue(MyItemProperty, value); }
    }

    public static readonly DependencyProperty MyItemProperty =
        DependencyProperty.Register("MyItem", typeof(MyItem), typeof(MyItemControl), new PropertyMetadata(null, MyItemPropertyChanged));

    private static void MyItemPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        MyItemControl sender = (MyItemControl)obj;
        sender.Sum = sender.MyItem.Num1 + sender.MyItem.Num2 + sender.MyItem.Num3;
        Console.WriteLine("Update sum");
    }

    public int Sum
    {
        get { return (int)GetValue(SumProperty); }
        set { SetValue(SumProperty, value); }
    }

    private static readonly DependencyProperty SumProperty =
        DependencyProperty.Register("Sum", typeof(int), typeof(MyItemControl), new PropertyMetadata(0));

}