WPF从ListView获取控制变量

时间:2014-09-13 18:09:43

标签: c# wpf binding row

我正在使用WPF进行聊天,我为{strong>会议室列表设计了ListView

MainWindow.xaml

<ListView x:Name="listView_RoomList" Grid.Row="1" Grid.ColumnSpan="2"   
          ScrollViewer.HorizontalScrollBarVisibility="Visible" SelectionMode="Single"
          Visibility="{Binding ElementName=comboBox_CntList, Path=Items.IsEmpty,
                                      Converter={StaticResource VisibilityConverter}}">
    <ListView.View>
        <GridView ColumnHeaderTemplate="{Binding Path=Rooms}">
            <GridView.Columns>
                <GridViewColumn x:Name="gridViewColumn_RoomName" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=Name}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn x:Name="gridViewColumn_Master" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=Master}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn x:Name="gridViewColumn_MaxConnectorNum">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=MaxConnectorNum, Converter={StaticResource MaxConnectorNumConverter}}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn x:Name="gridViewColumn_IsNeedPassword">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <PasswordBox x:Name="passwordBox_PW" MinWidth="100" IsEnabled="{Binding Path=IsNeedPassword}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn x:Name="gridViewColumn_EntryButton">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Button Background="Aqua" Click="button_Entry_Click">
                                <StackPanel Orientation="Horizontal">
                                    <Image Height="Auto" Width="Auto" Source="Resources/login.png"/>
                                    <TextBlock Text="{Binding Converter={StaticResource EntryButtonConverter}}" VerticalAlignment="Center"/>
                                </StackPanel>
                                <Button.Tag>
                                    <!-- I can get a Room ID!! -->
                                    <Binding Path="ID"/>
                                </Button.Tag>
                            </Button>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn x:Name="gridViewColumn_DeleteButton">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Button Background="Orange" Click="button_Delete_Click" IsEnabled="{Binding Path=Master, Converter={StaticResource DeleteButtonVisibilityConverter}}">
                                <StackPanel Orientation="Horizontal">
                                    <Image Height="Auto" Width="Auto" Source="Resources/login.png"/>
                                    <TextBlock Text="{Binding Converter={StaticResource DeleteButtonConverter}}" VerticalAlignment="Center"/>
                                </StackPanel>
                            </Button>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>

一个GridView RowRoom个类。

Room.cs

public class Room
{
        public uint ID { get; private set; }

        public string Name { get; private set; }

        public string Master { get; internal set; }

        public short MaxConnectorNum { get; private set; }

        public bool IsNeedPassword { get; private set; }
}

每个房间都有 ID

因此,当调用button_Entry_Click函数时,我可以获得房间ID。

MainWindow.xaml.cs

private void button_Entry_Click(object sender, RoutedEventArgs e)
        {
            Button b = (Button)sender;

            MessageBox.Show(b.Tag);
        }

像这样的东西。

我可以得到Button 但是,我希望得到PasswordBox输入密码等...

因为我想找到从房间ID获取所有行控制的方法。

我如何编码?

提前致谢。

1 个答案:

答案 0 :(得分:1)

您需要从ListView获取容器并遍历它的VisualTree搜索PasswordBox 控制。

首先,这里有一些你可以使用的扩展,我总是随身携带。

public static class VisualTreeHelperExtensions
{
    public static T FindVisualParent<T>(DependencyObject depObj) where T : DependencyObject
    {
        var parent = VisualTreeHelper.GetParent(depObj);

        if (parent == null || parent is T)
            return (T)parent;

        return FindVisualParent<T>(parent);
    }

    public static T FindVisualChild<T>(DependencyObject depObj) where T : Visual
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                if (child != null && child is T)
                {
                    return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    return childOfChild;
                }
            }
        }
        return null;
    }

    public static T FindVisualChild<T>(DependencyObject depObj, string name) where T : FrameworkElement
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                if (child != null && child is T && (child as T).Name.Equals(name))
                {
                    return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    if (childOfChild.Name.Equals(name))
                        return childOfChild;
                }
            }
        }
        return null;
    }

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj == null)
            yield break;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

            if (child != null && child is T)
            {
                yield return (T)child;
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }               
}

现在,这是一个如何获取ListView中第一个房间的PasswordBox的示例:

CS:

    public List<Room> Rooms
    {
        get
        {
            return new List<Room> 
            { 
                new Room{ Name = "A"} , 
                new Room{ Name = "B"}
            };
        }
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        var rooms = listView_RoomList.Items.Cast<Room>().ToList();

        var generator = listView_RoomList.ItemContainerGenerator;

        ListViewItem container = (ListViewItem)generator.ContainerFromItem(rooms[0]);

        PasswordBox pwd = (PasswordBox)VisualTreeHelperExtensions.FindVisualChild<PasswordBox>(container);
        string password = pwd.Password;
    }

XAML:

  <Grid>
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition />
      </Grid.RowDefinitions>

       <Button Content="Submit" Click="Button_Click_1"  />

       <ListView x:Name="listView_RoomList" Grid.Row="1" ItemsSource="{Binding Rooms}"
              ScrollViewer.HorizontalScrollBarVisibility="Visible" SelectionMode="Single">
             <ListView.View>
                   <GridView>
                      <GridView.Columns>

                         <GridViewColumn>
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                   <TextBlock Text="{Binding Name}"/>
                                 </DataTemplate>
                             </GridViewColumn.CellTemplate>
                          </GridViewColumn>

                          <GridViewColumn>
                               <GridViewColumn.CellTemplate>
                                   <DataTemplate>
                                        <PasswordBox  />
                                   </DataTemplate>
                                </GridViewColumn.CellTemplate>
                           </GridViewColumn>                       
                    </GridView.Columns>
               </GridView>
           </ListView.View>
       </ListView>                
  </Grid>

或者您也可以这样做:

XAML:

     <GridViewColumn>
          <GridViewColumn.CellTemplate>
              <DataTemplate>                                  
                   <PasswordBox PasswordChanged="passwordBox_PW_PasswordChanged_1"  />
               </DataTemplate>
          </GridViewColumn.CellTemplate>
     </GridViewColumn>

CS:

    private void passwordBox_PW_PasswordChanged_1(object sender, RoutedEventArgs e)
    {
        PasswordBox pwdBox = (PasswordBox)sender;
        Room r = pwdBox.DataContext as Room;
        r.Password = pwdBox.Password;
    }