我在绑定(bind) UserControl 中的依赖属性时遇到问题。当它初始化时它得到一个值但随后它不会更新。我可能错过了一些明显的东西,这里有一些代码片段:
这是我绑定(bind) BalanceContent
依赖属性的地方:
<Game:PlayerDetails x:Name="SelectedPlayerDetails" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="4"
BalanceContent="{Binding Source={StaticResource UserData}, Path=SelectedUser.Balance, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
</Game:PlayerDetails>
这是 UserControl
中的 TextBox
:
<TextBox VerticalAlignment="Center" FontFamily="Formata" FontSize="20" Grid.Column="2"
Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}, Path=BalanceContent}"
Grid.Row="7"></TextBox>
这是依赖属性:
public static readonly DependencyProperty BalanceContentProperty = DependencyProperty.Register(
"BalanceContent", typeof(string), typeof(PlayerDetails));
public string BalanceContent
{
get
{return (string) GetValue(BalanceContentProperty);}
set
{SetValue(BalanceContentProperty, value);}
}
这是更新所选用户的列表,它位于使用 UserControl 的 View 中:
<ListView x:Name="lstAccounts" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Grid.RowSpan="4"
ItemsSource="{Binding Source={StaticResource UserData}, Path=CurrentUserSearch}"
SelectedItem="{Binding Source={StaticResource UserData}, Path=SelectedUser}"
SelectedUser
在这里定义在一个实现了 INotifyPropertyChanged
的类中:
public User SelectedUser
{
get
{
return _selectedUser;
}
set
{
_selectedUser = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedUser"));
}
}
想法是,当在列表中选择新用户时,TextBox 应该更新,但目前它没有这样做。我已将绑定(bind)放在本地 TextBox 上,它更新正常,只是不在 DependencyProperty
上。任何帮助表示赞赏。
最佳答案
您可以尝试一些可能性:
首先,您的 ListView 可能不会更新您的 ViewModel 的 SelectedUser 属性。尝试将 ListView 中的绑定(bind)设置为“TwoWay”模式:
<ListView x:Name="lstAccounts" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Grid.RowSpan="4"
ItemsSource="{Binding Source={StaticResource UserData}, Path=CurrentUserSearch}"
SelectedItem="{Binding Source={StaticResource UserData}, Path=SelectedUser, Mode=TwoWay}"/>
您可以更好地组织 DataContext 的定义方式。请记住,您的 UserControl 的所有子控件都可以访问其 DataContext 而无需使用相对绑定(bind)(它们继承它)。由于您的 PlayerInfo 控件依赖于 SelectedUser,请考虑将其 DataContext 设置为 SelectedUser,将其绑定(bind)到 ListView 的 SelectedUser 或 UserData View 模型中的 SelectedUser。
<Game:PlayerDetails x:Name="SelectedPlayerDetails" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="4" DataContext="{Binding Source={StaticResource UserData}, Path=SelectedUser}"
BalanceContent="{Binding Balance, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
</Game:PlayerDetails>
当前SelectedUser的来源也可以是ListView:
<Game:PlayerDetails x:Name="SelectedPlayerDetails" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="4" DataContext="{Binding SelectedItem, ElementName=lstAccounts}"
BalanceContent="{Binding Balance, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
</Game:PlayerDetails>
无论哪种方式,您都可以在 TextBox 上执行以下操作,因为它的 DataContext 将与其父项之一相同:
<TextBox VerticalAlignment="Center" FontFamily="Formata" FontSize="20" Grid.Column="2"
Text="{Binding Balance}"
Grid.Row="7"></TextBox>
如果 usercontrol 依赖于 Root View 模型来执行命令和其他高级逻辑,则将 DataContext 设置为可以轻松访问 SelectedUser 的方式。
<Game:PlayerDetails x:Name="SelectedPlayerDetails" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="4" DataContext="{StaticResource UserData}"
BalanceContent="{Binding SelectedUser.Balance, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
</Game:PlayerDetails>
所以你可以这样做:
<TextBox VerticalAlignment="Center" FontFamily="Formata" FontSize="20" Grid.Column="2"
Text="{Binding SelectedUser.Balance}"
Grid.Row="7"></TextBox>
但是,在第二种方法中,您必须检查一件我不确定的事情。我知道当控件的 DataContext 发生变化时,它会更新所有相关的绑定(bind)。例如,如果您将 PlayerDetails DataContext 更改为另一个 UserData 实例,则 BalanceContent 属性也会更新。但是,在这种情况下,BalanceContent 取决于 UserData 的 SelectedUser 的属性。因此它将监听该用户实例的属性更改。如果 SelectedUser.Balance 发生变化(并且 User 实现了 INotifyPropertyChanged,或者它是一个 DependencyProperty),BalanceContent 将更新。现在,如果 UserData 中的 SelectedUser 实例发生变化,我不确定 BalanceContent 是否会更新,因为我认为绑定(bind)不会监听其路径中每个对象的变化。
编辑
最后一点可能是我在使用 xaml 进行开发时遇到的第一个问题。我在 Silverlight 中有一个 DataGrid,其实体类型具有复杂类型的属性。其中一列取决于复杂类型的属性。如果我更改复杂类型的值,该列将更新正常(它实现了 INPC)。如果我更改实体的复杂类型实例,该列将不会... 解决方案是级联 DataContexts:我创建了一个模板列,为复杂类型设置列的绑定(bind),而不是它的属性。然后我将模板的 TextBox 的文本绑定(bind)到复杂类型的属性,因为它现在是 TextBox 的 DataContext。
在您的情况下,您可以为 TextBox.Text 执行此操作,但不能为 PlayerDetails.BalanceContent 执行此操作。您可以将 TextBox.DataContext 绑定(bind)到 UserData 的 SelectedUser,然后将 Text 绑定(bind)到 Balance 属性。
<TextBox VerticalAlignment="Center" DataContext="{Binding SelectedUser}" FontFamily="Formata" FontSize="20" Grid.Column="2"
Text="{Binding Balance}"
Grid.Row="7"></TextBox>
关于c# - WPF 绑定(bind)依赖属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13477486/