Доступ к RelativePanel в DataTemplate каждого ListViewItem в ListView UWP Windows 10

Я хочу получить доступ и изменить FlowDirection RelativePanel в каждом ListViewItem в его DataTemplate. Я попробовал именно этот метод, у меня была такая же ошибка: Как мне получить доступ к элементу управления внутри XAML DataTemplate? Я тоже пробовал данное решение, но у меня есть

_Container = MyFlipView.ItemContainerGenerator.ContainerFromItem(item);

всегда возвращать ноль, даже если мой item не равен нулю. Я пытался поместить UpdateLayout() перед ним, но тщетно. Я попытался разместить ожидание

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>{ } 

вокруг него, но тоже напрасно, всегда возвращая ноль. Это мой код:

  <ListView x:Name="MessagesListView">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalAlignment" Value="Stretch"/>
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="data:Message">
                <RelativePanel x:Name="RelativeDataTemplate" Background="White" Margin="10,5,10,5" MaxHeight="115" MinHeight="115" MinWidth="400" HorizontalAlignment="Stretch">                        
                    <TextBlock x:Name="MessageToBlock" Text="{x:Bind MessageTo}" FontSize="14"  TextAlignment="DetectFromContent" Foreground="Black" FontWeight="SemiBold" RelativePanel.RightOf="ImageEllipse" Height="20" Margin="10,30,10,20"/>
                    <TextBlock x:Name="AgentNameBlock" Text="{x:Bind AgentName}" Padding="10,0" TextAlignment="DetectFromContent" RelativePanel.RightOf="ImageEllipse" RelativePanel.Below="MessageToBlock" FontSize="14" Foreground="#2d73b5" FontWeight="SemiBold" Height="20"/>
                    <TextBlock x:Name="MessageDateBlock" Text="{x:Bind MessageDate}" TextAlignment="Right" FontSize="14" Foreground="Black" RelativePanel.AlignVerticalCenterWith="MessageToBlock" RelativePanel.AlignRightWithPanel="True" Height="20" Margin="0,30,20,20"/>
                    <TextBlock x:Name="MessageYearBlock" Text="{x:Bind MessageYear}" TextAlignment="Right" FontSize="14" Foreground="#2d73b5" RelativePanel.AlignVerticalCenterWith="AgentNameBlock" RelativePanel.AlignRightWithPanel="True" Margin="0,0,20,0"/>
                </RelativePanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

foreach (var item in myListView.Items)
                {

                    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        UpdateLayout();
                        myListView.ScrollIntoView(item);
                        var _Container = myListView.ItemContainerGenerator
                        .ContainerFromItem(item) as FrameworkElement;
                    var _Children = AllChildren(_Container);

                    var _RelativePanel = _Children
                        // only interested in RelativePanel
                        .OfType<RelativePanel>()
                        // only interested in RelativePanel
                        .First(x => x.Name.Equals("RelativeDataTemplate"));

                    // test & set color
                    _RelativePanel.FlowDirection = FlowDirection.RightToLeft;
                    });
                }

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

Какое-нибудь решение, которое я еще не нашел?


person yalematta    schedule 02.05.2016    source источник
comment
Зачем вам нужен доступ к RelativePanel в DataTemplate? Вы хотите знать DataContext ListViewItem?   -  person Grace Feng    schedule 03.05.2016
comment
Нет, мне нужно изменить FlowDirection RelativePanel на RightToLeft, чтобы все элементы в ListView перевернулись (поскольку язык изменится с английского на арабский).   -  person yalematta    schedule 03.05.2016
comment
Так, например, есть CheckBox, если этот CheckBox не отмечен, он течет слева направо, а если этот CheckBox отмечен, он течет справа налево? Должен быть триггер, чтобы это изменение произошло, иначе вы можете напрямую определить его в коде xaml, я прав?   -  person Grace Feng    schedule 03.05.2016
comment
Да, но вы не понимаете мой вопрос, я хочу знать, когда его следует изменить, когда вы хотите его вызвать. Например, событие нажатия кнопки или использование флажка или других пользовательских настроек. Если вы хотите сначала сделать поток справа налево, вы можете просто определить его в коде xaml, нет необходимости обращаться к нему в коде позади.   -  person Grace Feng    schedule 03.05.2016
comment
Да, триггер установлен на определенное событие ComboBox Selection_Changed, где я использую цикл foreach.   -  person yalematta    schedule 03.05.2016


Ответы (1)


Как мы уже обсуждали, вы использовали ComboBox для выбора языка (направления потока), поэтому для этого вы можете использовать привязку данных и конвертер, например:

<Page.Resources>
    <local:FlowDirectionConverter x:Key="cvt" />
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView x:Name="MessagesListView" ItemsSource="{x:Bind messagelist}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalAlignment" Value="Stretch" />
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:Message">
                <RelativePanel x:Name="RelativeDataTemplate" Background="White" Margin="10,5,10,5" MaxHeight="115" MinHeight="115" MinWidth="400" HorizontalAlignment="Stretch" FlowDirection="{Binding ElementName=comboBox, Path=SelectedItem,Converter={StaticResource cvt}}">
                    <TextBlock x:Name="MessageToBlock" Text="{x:Bind MessageTo}" FontSize="14"  TextAlignment="DetectFromContent" Foreground="Black" FontWeight="SemiBold"  Height="20" Margin="10,30,10,20" />
                    <TextBlock x:Name="AgentNameBlock" Text="{x:Bind AgentName}" Padding="10,0" TextAlignment="DetectFromContent"  RelativePanel.Below="MessageToBlock" FontSize="14" Foreground="#2d73b5" FontWeight="SemiBold" Height="20" />
                    <TextBlock x:Name="MessageDateBlock" Text="{x:Bind MessageDate}" TextAlignment="Right" FontSize="14" Foreground="Black" RelativePanel.AlignVerticalCenterWith="MessageToBlock" RelativePanel.AlignRightWithPanel="True" Height="20" Margin="0,30,20,20" />
                    <TextBlock x:Name="MessageYearBlock" Text="{x:Bind MessageYear}" TextAlignment="Right" FontSize="14" Foreground="#2d73b5" RelativePanel.AlignVerticalCenterWith="AgentNameBlock" RelativePanel.AlignRightWithPanel="True" Margin="0,0,20,0" />
                </RelativePanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <ComboBox x:Name="comboBox" VerticalAlignment="Bottom" ItemsSource="{x:Bind languagelist}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding language}" />
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</Grid>

код позади:

public ObservableCollection<Message> messagelist;
public ObservableCollection<MyLanguage> languagelist = new ObservableCollection<MyLanguage>();

public MainPage()
{
    this.InitializeComponent();
    messagelist = new ObservableCollection<Message>();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    //add data to messagelist
    languagelist.Clear();
    languagelist.Add(new MyLanguage { language = "English" });
    languagelist.Add(new MyLanguage { language = "Arabic" });
}

Класс MyLanguage довольно прост:

public class MyLanguage
{
    public string language { get; set; }
}

и мой конвертер такой:

public class FlowDirectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value != null)
        {
            var item = value as MyLanguage;
            if (item.language == "English")
                return FlowDirection.LeftToRight;
            else
                return FlowDirection.RightToLeft;
        }
        return FlowDirection.LeftToRight;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
person Grace Feng    schedule 03.05.2016
comment
Потрясающий метод! Спасибо! - person yalematta; 04.05.2016