28

私はこのフリップビューを持っています:

<FlipView x:Name="models_list" SelectionChanged="selectionChanged">
 <FlipView.ItemTemplate>
          <DataTemplate>
                <Grid x:Name="cv">
                        <Image x:Name="img1" Source = "{Binding ModelImage}" Stretch="Fill" Tag="{Binding ModelTag}"/>
                </Grid>
           </DataTemplate>
  </FlipView.ItemTemplate>

現在選択されているインデックスの img1 を見つけたいです。それを検索しているときに、ここの投稿でこの方法を見つけました:

private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
    {
        int childNumber = VisualTreeHelper.GetChildrenCount(control);
        for (int i = 0; i < childNumber; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(control, i);
            FrameworkElement fe = child as FrameworkElement;
            // Not a framework element or is null
            if (fe == null) return null;

            if (child is T && fe.Name== ctrlName)
            {
                // Found the control so return
                return child;
            }
            else
            {
                // Not found it - search children
                DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
                if (nextLevel != null)
                    return nextLevel;
            }
        }
        return null;
    }

フリップビューの最初のインデックスの画像を返しますが、現在選択されているインデックスに存在するものが必要です..このメソッドを編集しようとしましたが、必要なコントロールが見つかりません。誰でも私を助けることができますか?

4

6 に答える 6

56

発生している問題は、DataTemplateが繰り返され、コンテンツが によって生成されていることFlipViewです。はName、生成された前の兄弟 (または生成される次の兄弟) と競合するため、公開されません。

したがって、名前付き要素を取得するにDataTemplateは、最初に生成されたアイテムを取得し、次にその生成されたアイテム内で目的の要素を検索する必要があります。XAML の論理ツリーは、名前で物事にアクセスする方法であることを思い出してください。生成されたアイテムは論理ツリーにありません。代わりに、それらはビジュアル ツリーにあります (すべてのコントロールはビジュアル ツリーにあります)。つまり、参照したいコントロールを検索する必要があるビジュアル ツリーにあるということです。でこれVisualTreeHelperを行うことができます。

さて、それを行う方法は?

これについての記事を書いたのは、これが非常に繰り返される質問であるためです: http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html次のような再帰的メソッド:

public void TestFirstName()
{
    foreach (var item in MyFlipView.Items)
    {
        var _Container = MyFlipView.ItemContainerGenerator
            .ContainerFromItem(item);
        var _Children = AllChildren(_Container);

        var _FirstName = _Children
            // only interested in TextBoxes
            .OfType<TextBox>()
            // only interested in FirstName
            .First(x => x.Name.Equals("FirstName"));

        // test & set color
        _FirstName.Background = 
            (string.IsNullOrWhiteSpace(_FirstName.Text))
            ? new SolidColorBrush(Colors.Red)
            : new SolidColorBrush(Colors.White);
    }
}

public List<Control> AllChildren(DependencyObject parent)
{
    var _List = new List<Control>();
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
        var _Child = VisualTreeHelper.GetChild(parent, i);
        if (_Child is Control)
            _List.Add(_Child as Control);
        _List.AddRange(AllChildren(_Child));
    }
    return _List;
}

ここでの重要な問題は、このようなメソッドがすべての子を取得し、結果として得られる子コントロールのリストで、必要な特定のコントロールを検索できることです。わかる?

そして今、あなたの質問に答えるために!

現在選択されているアイテムが特に必要なため、次のようにコードを更新するだけです。

if (MyFlipView.SelectedItem == null)
    return;
var _Container = MyFlipView.ItemContainerGenerator
    .ContainerFromItem(MyFlipView.SelectedItem);
// then the same as above...
于 2013-05-08T17:24:22.923 に答える
13

もう少し一般的なアプローチは、次のようなものかもしれません。

private List<Control> AllChildren(DependencyObject parent)
{
    var _List = new List<Control>();
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
       var _Child = VisualTreeHelper.GetChild(parent, i);
       if (_Child is Control)
       {
        _List.Add(_Child as Control);
       }
      _List.AddRange(AllChildren(_Child));
    }
    return _List;
 } 


private T FindControl<T> (DependencyObject parentContainer, string controlName)
{            
        var childControls = AllChildren(parentContainer);
        var control = childControls.OfType<Control>().Where(x => x.Name.Equals(controlName)).Cast<T>().First();           
        return control;
}

次のように FindControl を呼び出します。

var parentContainer = this.flipView.ItemContainerGenerator.ContainerFromItem(this.flipView.SelectedItem);
var myImage = FindControl<Image>(parentContainer, "img1");

//suppose you want to change the visibility
myImage.Visibility = Windows.UI.Xaml.Visibility.Collapsed;         
于 2013-08-29T22:07:23.820 に答える
3

DataTemplate 内の要素にアクセスするための簡単な解決策は、DataTemplate のコンテンツを UserControl にラップすることです。これにより、ItemsControl のアイテム内のすべての UI 要素にアクセスできます。FlipView は通常そのアイテムを仮想化すると思うので、100 個のアイテムがバインドされていても、実際には 2 ~ 3 個だけが UI に現在の表現を持っている可能性があります (そのうちの 1 ~ 2 個は非表示)。何かを置き換えて、アイテムがコントロールにロードされたときにのみ実際に変更を加えます。

ItemsSource 内のアイテムを表すアイテム コンテナーを本当に識別する必要がある場合は、FlipView のItemContainerGeneratorプロパティとそのContainerFromItem()メソッドを確認できます。

アイテムの座標を取得するにはGetBoundingRect()、WinRT XAML Toolkit の拡張メソッドを使用できます。

ただし、全体として、あなたのコメントに基づいて、最良のアプローチは実際にはまったく異なる可能性があります. FlipView をソースにバインドしている場合 - 通常、バインドされたソース コレクション項目のプロパティを変更することで、表示またはオーバーレイされた画像を制御できます。

于 2013-05-05T04:21:44.820 に答える
0

したがって、バインディングを介して Source を割り当てた場合、rest で同じことをしないのはなぜですか。 <FlipView SelectedIndex="{Binding SIndex}" SelectedItem="{Binding SItem}" SelectedValue="{Binding SValue}"/>

まず、このプロパティの場所を準備する必要があります。から派生したクラスである可能性がありますINotifyPropertyChanged

MVVMを雇ってあなたのために働き、ほとんどのことを XAML で行います。もちろん、最初はもっと手間がかかるように見えますが、MVVM を使用したより洗練されたプロジェクトでは、一貫性と柔軟性が向上します。

于 2016-10-20T10:56:50.317 に答える