列表框中的所选项目始终是上一项

时间:2010-10-04 02:49:10

标签: wpf

真的有问题调试这个...原因可能很简单,但我仍然是WPF的业余爱好者。

如果您看到代码会更容易,但我会告诉您具体的问题。我的列表框设置为包含网格格式,每个listboxitem都有一个ListBoxItem.PreviewMouseLeftButtonDown事件。问题是,所选项目始终设置为上一项。

以下是步骤中发生的事情:

  1. 我的图片加载

  2. 我单击一个按钮在图像上生成32x32单元格的网格覆盖图,每个单元格在该覆盖图的单元格中

  3. 我点击一个单元格

  4. OnSelected方法触发(每个listboxitem通过Selected事件绑定到此处理程序)

  5. 当我点击单元格(0,0)

  6. 时,SelectedItem为空
  7. 如果单击单元格(0,1),则会触发Selected事件,但现在将SelectedItem设置为上一个单元格(0,0)中的对象而不是(0,1)。然后,单击(0,0)将显示SelectedItem为(0,1),依此类推。

  8. 重复任何其他单元格。

  9. XAML

     <DockPanel Name="dockTest">
            <Menu DockPanel.Dock="Top" Width="Auto" Height="Auto">
                <MenuItem Header="File">
                    <MenuItem Header="Load Image" Command="Open"></MenuItem>
                    <Separator />
                    <MenuItem Header="Exit" Command="Close"></MenuItem>
                </MenuItem>
            </Menu>
            <ListBox Name="lstTiles" DockPanel.Dock="Right" PreviewMouseRightButtonDown="grdMain_MouseRightButtonDown" 
                 PreviewMouseRightButtonUp="grdMain_MouseRightButtonUp"  SelectionMode="Extended">
                <ListBox.ItemContainerStyle>
                    <Style>
                    <EventSetter Event="ListBoxItem.Selected" Handler="OnSelected" />
                    <Setter Property="ListBox.RenderTransformOrigin" Value="0.5,0.5" />
                    <Setter Property="Grid.Row" Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=Content.Row}"/>
                        <Setter Property="Grid.Column" Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=Content.Column}"/>
                        <Setter Property="ListBoxItem.Height" Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=Content.Height}" />
                        <Setter Property="ListBoxItem.Width" Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=Content.Width}" />
                    <Setter Property="ListBoxItem.IsHitTestVisible" Value="True" />
                    <Style.Resources>
                            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Blue" Opacity=".3" />
                            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
                        </Style.Resources>
                    </Style>
                </ListBox.ItemContainerStyle>
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid ShowGridLines="True" IsItemsHost="True" Background="{DynamicResource LoadedImage}" 
                          Name="grdMain" MaxHeight="600" MaxWidth="800" MinHeight="600" MinWidth="800" >
                        </Grid>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
            </ListBox>
        <StackPanel DockPanel.Dock="Left">
            <Label Margin="5">Tile Size</Label>
            <ComboBox Name="cmbGridSize">
                <TextBlock Name="txt3232">32x32</TextBlock>
                <TextBlock Name="txt1616">16x16</TextBlock>
                <TextBlock Name="txt88">8x8</TextBlock>
            </ComboBox>
            <Button Name="btnChangeGrid" Click="GridBtn_Click" Margin="4">Make Grid</Button>
            <Label>Tile Type</Label>
            <ComboBox Name="cmbTileType" SelectionChanged="cmbTileType_SelectionChanged">
    
            </ComboBox>
            <TextBlock Name="txtTest"></TextBlock>
            <Label>Tile Characteristic</Label>
            <ComboBox Name="cmbTileCharacteristic" SelectionChanged="cmbTileCharacteristic_SelectionChanged">
            </ComboBox>
            <Button Name="btnExport" Click="btnExport_Click">Export</Button>
            <Label>Edit Cell</Label>
            <Button Name="btnEdit" Click="btnEdit_Click">Edit Cell</Button>
        </StackPanel>
    </DockPanel>
    

    代码背后

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            //Stores enum array of tile type enums
            tileTypes = Enum.GetNames(typeof(Tile.TileType));
    
            //Stores enum array of tile characteristics
            tileCharacteristics = Enum.GetNames(typeof(Tile.TileCharacteristic));
    
            //Gets main grid in template of main page
            mainGrid = Helpers.FindItemsPanel(lstTiles) as Grid;
    
            //Sets combobox to array of types of tiles
            cmbTileType.ItemsSource = tileTypes;
    
            //Sets combobox to array of characteristics
            cmbTileCharacteristic.ItemsSource = tileCharacteristics;
    
        }  //Generates the grid overlay
        private void Grid_Build()
        {
            //Sets grid overlay to user preferences of tile size
            if (tileList.Count > 0)
            {
                tileList.Clear();
            }
    
            if (mainGrid.RowDefinitions.Count > 0)
            {
                mainGrid.RowDefinitions.Clear();
            }
    
            if (mainGrid.ColumnDefinitions.Count > 0)
            {
                mainGrid.ColumnDefinitions.Clear();
            }
    
            int numberOfColumns = Convert.ToInt32(Math.Ceiling((float)imageWidth / (float)dimension));
            int numberOfRows = Convert.ToInt32(Math.Ceiling((float)imageHeight / (float)dimension));
    
            for (int i = 0; i < numberOfRows; i++)
            {
                mainGrid.RowDefinitions.Add(new RowDefinition());
            }
    
            for (int i = 0; i < numberOfColumns; i++)
            {
                mainGrid.ColumnDefinitions.Add(new ColumnDefinition());
            }
    
            int addCounter = 0;
    
            //Stores and generates tile objects in generated rows and columns
            for (int row = 0; row < numberOfRows; row++)
            {
                for (int col = 0; col < numberOfColumns; col++)
                {
                    Tile tempTile = (new Tile(row, col, dimension, dimension, addCounter, Tile.TileType.None, Tile.TileCharacteristic.Empty));
                    tempTile.IsHitTestVisible = true;
                    tileList.Add(tempTile);
                    addCounter++;
                }
            }
    
            //Sets listbox of tiles in xaml to the list of tile objects
            lstTiles.ItemsSource = tileList;
        }
    
        //Occurs when a listbox item is selected
        private void OnSelected(object sender, RoutedEventArgs e)
        {
            //If a single tile object is selected
            if (lstTiles.SelectedItems.Count == 1)
            {
                //Stores array of selected tile listboxitems in listbox
                var items = lstTiles.SelectedItems;
    
                foreach (Tile it in items)
                {
                    txtTest.Text = it.Row.ToString() + " " + it.Column.ToString();
    
                    //Sets tile type combobox to the property set in each tile object
                    cmbTileType.SelectedItem = (string)Enum.GetName(typeof(Tile.TileType), it.Type);
    
                    //Sets tile characteristic combobox to the property set in each tile object
                    cmbTileCharacteristic.SelectedItem = (string)Enum.GetName(typeof(Tile.TileCharacteristic), it.Characteristic);
                }
            }
        }
    

3 个答案:

答案 0 :(得分:1)

可能是因为您正在使用预览鼠标,您的鼠标按下事件在列表框收到它之前触发并正确设置正确的项目以进行选择。尝试切换到鼠标左键,然后看看是否能解决问题。

答案 1 :(得分:0)

您的代码似乎与您的说明不符。您说OnSelected方法会因PreviewLeftMouseButtonDown而触发,但您的XAML有:

<EventSetter Event="ListBoxItem.Selected" Handler="OnSelected" />

如果您通过OnSelected事件调用了Preview方法,那么您的问题就非常有意义了。在控件处理它们之前会引发Preview个事件,因此尚未制定选择。这使您有机会有效地取消事件,以便它永远不会“到达”控件。

因此,考虑到这一点,您可以在第一次选择项目时理解SelectedItemnull的原因 - ListBox尚未有机会应用选择。由于同样的原因,随后的选择将始终是一步。

如果您的事件处理程序依赖于已制定的选择,那么您需要确保在ListBox有机会应用它们之后触发它们。 ListBoxItem.Selected事件就足够了。这就是我对你的代码感到困惑的原因。

答案 2 :(得分:0)

选择问题是获取列表框的selecteditems容器的过早事件。我应该使用的是SelectionChanged