繁体   English   中英

如何在Silverlight中正确通知将一个自定义属性从另一属性更改为绑定到不同控件的方法?

[英]How in Silverlight correctly notify to change one custom property from another property binding to different controls?

我有这个MainPage.xaml:

<UserControl x:Class="SilverlightApplication2.MainPage"
    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"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" Height="246" Width="562">

        <Grid HorizontalAlignment="Left" Width="552" ShowGridLines="True" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
            <ColumnDefinition Width="275" />
                <ColumnDefinition Width="113"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="45" />
                <RowDefinition Height="45" />
                <RowDefinition Height="45" />
                <RowDefinition Height="45" />
                <RowDefinition Height="45" />
            </Grid.RowDefinitions>
        <Slider x:Name="sliderLoanAmount" Value="{Binding LoanAmount, Mode=TwoWay}" Height="35" SmallChange="1" LargeChange="10000" Minimum="0" Maximum="700000" HorizontalAlignment="Left" VerticalAlignment="Center" Width="265" Margin="0" TabIndex="1" />
        <TextBox Grid.Column="1" x:Name="textLoanAmount" Text="{Binding LoanAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="70" VerticalAlignment="Center" Margin="0,12" Foreground="Blue" FontSize="14" FontStretch="Normal" TextAlignment="Left" FontWeight="Bold" Padding="0" TabIndex="2" />

        <Slider x:Name="sliderDownPaymentPercent" Value="{Binding DownPaymentPercent, Mode=TwoWay}" SmallChange="1" LargeChange="10" Minimum="0" Maximum="100" HorizontalAlignment="Left" Width="265" Height="35" VerticalAlignment="Center" Margin="0" Grid.Row="1" TabIndex="3" />
        <TextBox Grid.Row="1" Grid.Column="1" x:Name="textDownPaymentAmount" Text="{Binding DownPaymentAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="70" VerticalAlignment="Center" Margin="0,12" Foreground="Blue" FontSize="14" FontStretch="Normal" TextAlignment="Left" FontWeight="Bold" Padding="0" TabIndex="3" />

        </Grid>
</UserControl>

我也有自定义的LoanData类,其属性绑定到滑块和文本框控件:

public partial class MainPage : UserControl
{
    private LoanData Loan
    {
        get;
        set;
    }

    public MainPage()
    {
        InitializeComponent();

        this.Loan = new LoanData { LoanAmount = 700000, DownPaymentPercent = 20, DownPaymentAmount = 140000};
        this.DataContext = this.Loan;
    }
}

public class LoanData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private long _LoanAmount;
    public long LoanAmount
    {
        get { return _LoanAmount; }
        set
        {
            if (_LoanAmount != value)
            {
                _LoanAmount = value;
                NotifyPropertyChanged("LoanAmount");
            }
        }
    }

    private long _DownPaymentPercent;
    public long DownPaymentPercent
    {
        get { return _DownPaymentPercent; }
        set
        {
            if (_DownPaymentPercent != value)
            {
                _DownPaymentPercent = value;
                NotifyPropertyChanged("DownPaymentPercent");

                DownPaymentAmount = DownPaymentAmount;
                //NotifyPropertyChanged("DownPaymentAmount");
            }
            else
            {
                if (LoanAmount != 0)
                {
                    _DownPaymentPercent = (DownPaymentAmount / LoanAmount) * 100;
                    NotifyPropertyChanged("DownPaymentPercent");
                }
            }
        }
    }

    private long _DownPaymentAmount;
    public long DownPaymentAmount
    {
        get { return _DownPaymentAmount; }
        set
        {
            if (_DownPaymentAmount != value)
            {
                _DownPaymentAmount = value;
                NotifyPropertyChanged("DownPaymentAmount");

                DownPaymentPercent = DownPaymentPercent;
                //NotifyPropertyChanged("DownPaymentPercent");
            }
            else
            {
                _DownPaymentAmount = (DownPaymentPercent * LoanAmount) / 100;
                NotifyPropertyChanged("DownPaymentAmount");
            }
        }
    }

}

控制与LoanAmount属性绑定的sliderLoanAmount和textLoanAmount。 更改滑块位置会导致更改文本值,反之亦然。

但是接下来的两个控件需要更复杂的逻辑。 重新定位sliderDownPaymentPercent控件时,textDownPaymentAmount值必须为DownPaymentAmount =(DownPaymentPercent * LoanAmount)/100。当我更改textDownPaymentAmount控件中的值时,sliderDownPaymentPercent必须重新定位为值DownPaymentPercent =(DownPaymentAmount / LoanAmount)* 100。

当我重新定位sliderDownPaymentPercent时,执行以下代码:

if (_DownPaymentPercent != value)
{
    _DownPaymentPercent = value;
    NotifyPropertyChanged("DownPaymentPercent");

    DownPaymentAmount = DownPaymentAmount;
    //NotifyPropertyChanged("DownPaymentAmount");
}

我想告诉textDownPaymentAmount通过调用更改其值

NotifyPropertyChanged("DownPaymentAmount");

但它不起作用,我发现的唯一解决方案是:

 DownPaymentAmount = DownPaymentAmount;

这导致执行此代码:

else
{
    _DownPaymentAmount = (DownPaymentPercent * LoanAmount) / 100;
    NotifyPropertyChanged("DownPaymentAmount");
}

当我输入textDownPaymentAmount执行代码时:

if (_DownPaymentAmount != value)
{
    _DownPaymentAmount = value;
    NotifyPropertyChanged("DownPaymentAmount");

    DownPaymentPercent = DownPaymentPercent;
    //NotifyPropertyChanged("DownPaymentPercent");
}

如您所见,我必须再次打电话

DownPaymentPercent = DownPaymentPercent;

代替

 //NotifyPropertyChanged("DownPaymentPercent");

所以我的问题是如何正确通知从一个属性更改另一个属性而不使用此属性:

DownPaymentPercent = DownPaymentPercent;

要么

DownPaymentAmount = DownPaymentAmount;

我认为问题在于您为属性使用long类型,并且滑块值必须为double类型。

尝试这个:

    <Slider x:Name="sliderLoanAmount" Value="{Binding LoanAmount, Mode=TwoWay}" Height="35" SmallChange="1" LargeChange="10000" Minimum="0" Maximum="700000" HorizontalAlignment="Left" VerticalAlignment="Center" Width="265" Margin="0" TabIndex="1" />
    <TextBox Grid.Column="1" x:Name="textLoanAmount" Text="{Binding LoanAmount, Mode=TwoWay}" Width="70" VerticalAlignment="Center" Margin="0,12" Foreground="Blue" FontSize="14" FontStretch="Normal" TextAlignment="Left" FontWeight="Bold" Padding="0" TabIndex="2" />

    <Slider x:Name="sliderDownPaymentPercent" Value="{Binding DownPaymentPercent, Mode=TwoWay}" SmallChange="1" LargeChange="10" Minimum="0" Maximum="100" HorizontalAlignment="Left" Width="265" Height="35" VerticalAlignment="Center" Margin="0" Grid.Row="1" TabIndex="3" />
    <TextBox Grid.Row="1" Grid.Column="1" x:Name="textDownPaymentAmount" Text="{Binding DownPaymentAmount, Mode=TwoWay}" Width="70" VerticalAlignment="Center" Margin="0,12" Foreground="Blue" FontSize="14" FontStretch="Normal" TextAlignment="Left" FontWeight="Bold" Padding="0" TabIndex="3" />

public class LoanData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private double _LoanAmount;
    public double LoanAmount
    {
        get { return _LoanAmount; }
        set
        {
            if (_LoanAmount != value)
            {
                _LoanAmount = value;
                NotifyPropertyChanged("LoanAmount");
                DownPaymentAmount = (DownPaymentPercent / 100) * LoanAmount;
            }
        }
    }

    private double _DownPaymentPercent;
    public double DownPaymentPercent
    {
        get { return _DownPaymentPercent; }
        set
        {
            if (_DownPaymentPercent != value)
            {
                _DownPaymentPercent = value;
                NotifyPropertyChanged("DownPaymentPercent");
                DownPaymentAmount = (DownPaymentPercent / 100) * LoanAmount;
            }
        }
    }

    private double _DownPaymentAmount;
    public double DownPaymentAmount
    {
        get { return _DownPaymentAmount; }
        set
        {
            if (_DownPaymentAmount != value)
            {
                _DownPaymentAmount = value;
                NotifyPropertyChanged("DownPaymentAmount");
                DownPaymentPercent = (DownPaymentAmount / LoanAmount) * 100;
            }
        }
    }

}

我想我在这里看到了问题:在您的DownPaymentPercent和DownPaymentAmount的设置程序中,您都对后备字段_DownPaymentPercent进行重新计算。 _DownPaymentAmount每当“新”值与“旧”值相同时。 看到:

if (_DownPaymentAmount != value)
{
   /*snip*/
}
else
{
    _DownPaymentAmount = (DownPaymentPercent * LoanAmount) / 100;
    NotifyPropertyChanged("DownPaymentAmount");
}

这意味着您的语句DownPaymentPercent = DownPaymentPercent; 实际上会更改DownPaymentPercent的值(并触发NotifyPropertyChanged)。 因此,您(现在已注释掉)的NotifyPropertyChanged调用实际上可以正常工作,但是可惜! 后备字段的值仍然是旧值(没有进行重新计算,实际上已更新了绑定,但是您没有看到UI更改,因为您的DataContext提供了已经显示的相同值)。 为了解决这个问题,每次使用新值调用一个setter时,都必须重新计算其他从属值:

//setter for DownPaymentAmount...
set
{
    if (_DownPaymentAmount != value)
    {
        _DownPaymentAmount = value;
        NotifyPropertyChanged("DownPaymentAmount");

        //recalculate dependent property backing field
        if (LoanAmount != 0)
        {
            _DownPaymentPercent = (DownPaymentAmount / LoanAmount) * 100;
            NotifyPropertyChanged("DownPaymentPercent");
        }
    }
}

//...and setter for DownPaymentPercent
set
{
    if (_DownPaymentPercent != value)
    {
        _DownPaymentPercent = value;
        NotifyPropertyChanged("DownPaymentPercent");

        //recalculate dependent property backing field
        _DownPaymentAmount = (DownPaymentPercent * LoanAmount) / 100;
        NotifyPropertyChanged("DownPaymentAmount");
    }
}

[编辑]您的语句_DownPaymentPercent = (DownPaymentAmount / LoanAmount) * 100; 由于整数运算,最有可能导致_DownPaymentPercent变为0。 DownPaymentAmount / LoanAmount结果为0,将0乘以100仍为0。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM