C# 如何在Silverlight中正确地通知将一个自定义属性从另一个属性绑定更改为不同的控件?
我有这个MainPage.xaml:C# 如何在Silverlight中正确地通知将一个自定义属性从另一个属性绑定更改为不同的控件?,c#,silverlight,C#,Silverlight,我有这个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/e
<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>
控制sliderLoanAmount和textLoanAmount绑定到LoanAmount属性。更改滑块位置会导致更改文本值,反之亦然
但我需要为接下来的两个控件提供更复杂的逻辑。
当我重新定位sliderDownPaymentPercent控件文本DownPaymentAmount值必须为DownPaymentAmount=DownPaymentPercent*LoanAmount/100。
当我更改文本DownPaymentAmount控件滑块DownPaymentPercent中的值时,必须重新定位为值DownPaymentPercent=DownPaymentAmount/LoanAmount*100
当我重新定位sliderDownPaymentPercent时,执行以下代码:
if (_DownPaymentPercent != value)
{
_DownPaymentPercent = value;
NotifyPropertyChanged("DownPaymentPercent");
DownPaymentAmount = DownPaymentAmount;
//NotifyPropertyChanged("DownPaymentAmount");
}
else
{
_DownPaymentAmount = (DownPaymentPercent * LoanAmount) / 100;
NotifyPropertyChanged("DownPaymentAmount");
}
我想通过呼叫告诉textDownPaymentAmount更改其值
NotifyPropertyChanged("DownPaymentAmount");
但它不起作用,也是我找到的唯一解决方案:
DownPaymentAmount = DownPaymentAmount;
这将导致执行此代码:
if (_DownPaymentPercent != value)
{
_DownPaymentPercent = value;
NotifyPropertyChanged("DownPaymentPercent");
DownPaymentAmount = DownPaymentAmount;
//NotifyPropertyChanged("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;
或
我认为问题在于您使用的是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;
}
}
}
}
我想我在这里看到了问题: 在首付百分比和首付金额的设置器中,您重新计算支持字段_downpaymentpercentresp_当新值与旧值相同时,首付金额。 见: 这意味着您的对账单DownPaymentPercent=DownPaymentPercent;实际更改DownPaymentPercent的值并触发NotifyPropertyChanged。 因此,您现在注释掉的NotifyPropertyChanged调用实际上起了作用,但唉!backing字段的值仍然是旧值没有重新计算,绑定实际上已更新,但您在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。
首付金额/LoanAmount结果为0,0乘以100仍然是0。谢谢Rob!实际上,我有自定义的派生滑块,它可以处理lond值而不是double值。我的问题是如何从一个属性通知另一个属性,而不使用像DownPaymentAmount=DownPaymentAmount这样的代码。我不明白为什么当其他属性的值没有更改时,您需要通知另一个属性已更改?您会注意到,在我建议的解决方案中,我也做了同样的事情,将计算移到if语句内部。在_DownPaymentPercent的setter中,NotifyPropertyChangedDownPaymentAmount不是必需的,因为如果值实际发生更改,则应在_DownPaymentAmountsetter中发生。我的解决方案略有不同:我不调用setter,而是直接操作backing字段,因此我必须显式调用NotifyPropertyChanged,我敢说这并不是没有必要的,因为价值确实发生了变化。由于舍入错误,您的解决方案运行risc触发两个相关值的循环更新,我确信它将终止。明白了。我遵循的模式是更新公共变量并让setter处理NotifyPropertyChanged。我的解决方案不应使用!=值检查。
//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");
}
}