5

UserControlの依存関係プロパティのバインドに問題があります。初期化すると値を取得しますが、更新されません。私はおそらく明らかな何かを見逃しました、ここにいくつかのコードスニペットがあります:

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>

これが:TextBoxにありUserControlます

 <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を使用するビューにあります。

<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を更新する必要があるということですが、現時点では更新されていません。バインディングをローカルのTextBoxに配置しましたが、ではなく正常に更新されますDependencyProperty。助けていただければ幸いです。

4

5 に答える 5

4

あなたが試すことができるいくつかの可能性があります:

まず、ListViewがViewModelのSelectedUserプロパティを更新していない可能性があります。ListViewのバインディングを「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にアクセスできることに注意してください(それらはそれを継承します)。PlayerInfoコントロールはSelectedUserに依存しているため、DataContextをSelectedUserに設定することを検討してください。これは、ListViewのSelectedUserまたはUserDataビューモデルの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>

どちらの方法でも、DataContextは親のデータコンテキストと同じになるため、TextBoxで次のことができるようになります。

<TextBox  VerticalAlignment="Center" FontFamily="Formata" FontSize="20" Grid.Column="2" 
     Text="{Binding Balance}" 
         Grid.Row="7"></TextBox>

ユーザーコントロールがコマンドやその他の高レベルロジックなどのルートビューモデルに依存している場合は、SelectedUserに簡単にアクセスできるようにDataContextを設定します。

<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>

ただし、この2番目のアプローチでは、私がよくわからないことを1つ確認する必要があります。コントロールのDataContextが変更されると、すべての依存バインディングが正常に更新されることを私は知っています。たとえば、PlayerDetails DataContextを別のUserDataインスタンスに変更した場合、BalanceContentプロパティも更新されます。ただし、この場合、BalanceContentはUserDataのSelectedUserのプロパティに依存します。したがって、Userのそのインスタンスのプロパティの変更をリッスンします。SelectedUser.Balanceが変更された場合(およびユーザーがINotifyPropertyChangedを実装した場合、またはそれがDependencyPropertyである場合)、BalanceContentが更新されます。ここで、UserDataのSelectedUserインスタンスが変更された場合、BalanceContentが更新されるかどうかはわかりません。これは、バインディングがそのパス内のすべてのオブジェクトの変更をリッスンするとは限らないと思うためです。

編集

最後のポイントは、xamlで開発するときに私が最初に直面した問題でした。SilverlightにDataGridがあり、そのエンティティタイプには複合タイプのプロパティがありました。列の1つは、複合型のプロパティに依存していました。複合型の値を変更すると、列は正常に更新されます(INPCが実装されています)。エンティティの複合型インスタンスを変更した場合、列は変更されません...解決策は、DataContextsをカスケードすることでした。テンプレート列を作成し、プロパティではなく、複合型の列のバインディングを設定しました。次に、テンプレートのTextBoxのテキストをcomplextypeのプロパティにバインドしました。これは、TextBoxのDataContextになっているためです。

あなたの場合、TextBox.Textに対しては実行できますが、PlayerDetails.BalanceContentに対しては実行できません。TextBox.DataContextをUserDataのSelectedUserにバインドしてから、TextをBalanceプロパティにバインドできます。

<TextBox  VerticalAlignment="Center" DataContext="{Binding SelectedUser}" FontFamily="Formata" FontSize="20" Grid.Column="2" 
 Text="{Binding Balance}" 
     Grid.Row="7"></TextBox>
于 2012-11-21T11:49:41.913 に答える
1

ユーザーコントロール内のテキストボックスのバインドを変更して、ユーザーコントロールの依存関係プロパティであるBalanceContentにバインドしてからテストしてください(元のバインドソースはデータコンテキストプロパティのようです)

Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}, Path=BalanceContent}"

編集:次のコードを試してください

public User SelectedUser
    {
        get
        {
            return _selectedUser;
        } 
        set
        {
            _selectedUser = value;
            OnPropertyChanged(new PropertyChangedEventArgs("SelectedUser"));
            OnPropertyChanged(new PropertyChangedEventArgs("SelectedUserBalance"));
        }
    }

public string SelectedUserBalance
    {
        get
        {
            return _selectedUser.Balance;
        } 
    }

<Game:PlayerDetails x:Name="SelectedPlayerDetails" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="4" 
                          BalanceContent="{Binding Source={StaticResource UserData}, Path=SelectedUserBalance, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">

</Game:PlayerDetails>

<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>
于 2012-11-20T16:31:29.963 に答える
0

テキストボックスはUserControlsにバインドしようとしていDataContextます。x:NameUsercontrol定義にを与え、 TextBoxのDataContextをに設定しますDataContext="{Binding ElementName=[YourControlName]}"

于 2012-11-20T16:23:55.640 に答える
0
<TextBox VerticalAlignment="Center" FontFamily="Formata" FontSize="20" Grid.Column="2" 
       Text="{Binding SelectedItem.BalanceContent, ElementName=lstAccounts}" Grid.Row="7"></TextBox>

UserControlのバインドを忘れ、TextBoxをSelectedItemに直接バインドします。これがお役に立てば幸いです。

于 2012-11-20T16:29:36.947 に答える
0

StaticResourceをプロパティにバインドしています。DynamicResourcesとは対照的に、StaticResourcesは、Window(またはUserControl)が初期化されているときに一度だけロードされます。DynamicResourcesは、必要な場合にのみ(および必要な場合は毎回)ロードされます。DynamicResourceに加えられた変更はすべてすぐに取得され、それに応じてプロパティが更新されます。キーワード「StaticResource」を「DynamicResource」に置き換えるだけで、リソースが変更されるたびにプロパティバインディングが更新されます。

注:StaticResourceがFreezableクラスから派生したオブジェクトである場合、それもDynamicResourceのように動作します。たとえば、リソースがBrushの場合、Brushオブジェクトを何らかの方法で(不透明度を変更するなどして)変更するたびに、バインドされたプロパティが更新されますが、これはFreezableクラスから継承された動作によるものです。ただし、StaticResourceのBrushオブジェクトを新しいBrushオブジェクトに置き換えると、BrushではなくStaticであるリソースに変更が加えられているため、この変更は反映されません。

注:データSystemColors、SystemFonts(システム設定へのアクセスを提供する)など、StaticResourcesとしてのみ使用可能なリソースでも、DynamicResourceでラップして、変更のたびにプロパティが更新されるようにすることができます。これは次の方法で実行できます。

<Control Property="{DynamicResource {x:Static SystemColors.XXX}}"></Control>

于 2014-07-29T22:43:48.763 に答える