开发者

How to get binded ListboxItems from ListView in WPF

I'm pretty new to WPF so excuse me for any dumb question...

I have a ListView 开发者_StackOverflow中文版with three columns that is binded to a XmlDataProvider source like the following:

        <XmlDataProvider x:Key="Properties" XPath="/Info">
        <x:XData>
            <Info xmlns="">
                <Property Name="Text" Value=""/>                <!--0-->
                <Property Name="Tooltip" Value=""/>             <!--1-->
                <Property Name="Enable" Value=""/>              <!--2-->
                <Property Name="Visible" Value=""/>             <!--3-->
                <Property Name="Focus" Value=""/>               <!--4-->
                <Property Name="Selected" Value=""/>            <!--5-->
                <Property Name="Count" Value=""/>               <!--6-->
                <Property Name="Item" Value=""/>                <!--7-->
                <Property Name="SelectedText" Value=""/>        <!--8-->
                <Property Name="SelectedIndex" Value=""/>       <!--9-->
                <Property Name="Complete" Value=""/>            <!--10-->
            </Info>
        </x:XData>
    </XmlDataProvider>

The ListView is defined as following:

        <ListView Name="lstProperties"  Margin="55 0 0 0" Style="{DynamicResource TsListView}"
        Grid.Row="2" Grid.RowSpan="7" Grid.ColumnSpan="4"
        ItemsSource="{Binding Source={StaticResource Properties}, XPath=Property}" 
        ItemContainerStyle="{DynamicResource TsListViewItem}" 
        ScrollViewer.HorizontalScrollBarVisibility="Hidden"
        SelectionMode="Single" IsEnabled="False"
        SelectionChanged="propertySelected" 
        >

        <ListView.View>
            <GridView AllowsColumnReorder="False">
                <GridViewColumn CellTemplate="{StaticResource FirstCell}" Width="25" />
                <GridViewColumn Header="Property" Width="80">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <Label Style="{DynamicResource TsLabel}" Height="25" Width="115" Content="{Binding XPath=@Name}" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                <GridViewColumn Header="Value" Width="130">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Style="{DynamicResource TsHelperTextBox}"
                                     Height="20" Width="115" Text="{Binding XPath=@Value}" 
                                     IsEnabled="{Binding ElementName=rbTypeAssert, Path=IsChecked}" GotFocus="gridTextBox_GotFocus" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

What I want to do now is fairly simple: I just want to enable/disable some of the ListViewItems. The only way I found to get ListViewItems is through the following method:

lstProperties.ItemContainerGenerator.ContainerFromIndex(index)

This makes me a little uncomfortable. I should be getting the Items through the name property of Property. Is there anyway to do this? I'm also having problems when I try to do this right after the window is initialized. I get a NullReferenceException when trying to disable one of these ListViewItems. It seems that right after the window is rendered the binding is not done yet.


Kents answer is correct, but I would use a converter, instead of expanding your model:

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsEnabled" Value="{Binding Converter={StaticResource IsEnabledConverter}}"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

And the converter:

public class IsEnabledConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //Implement your logic here, and return true/false accordingly
        return true;
    }

    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }

    #endregion
}


The easiest and best way to do this is to expose a property that determines whether the ListViewItem should be enabled or not, and then bind to it:

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsEnabled" Value="{Binding YourProperty}"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>


Well your feedback, combined with other feedback received, allowed me to solve the problem. Thanks very much!

What I did was to add a new attribute, named IsEnable, to the Property in the XmlDataProvider, and then I binded the IsEnabled property of the ListViewItem to this new attribute. So instead of having one global property to define the state of all the ListViewItems, like you suggested, I'll have "individual binds".

To change the data programmatically I used the following method:

provider.Document.SelectSingleNode("//Property[Name=\"Text\"]/IsEnable").InnerText = false.ToString();

This method requires a slightly different format for the data. So the XmlDataProvider is now as following:

        <XmlDataProvider x:Key="Properties" XPath="/Info" IsAsynchronous="False" IsInitialLoadEnabled="True">
        <x:XData>
            <Info xmlns="">
                <Property>
                    <Name>Text</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Tooltip</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Enable</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Visible</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Focus</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Selected</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Count</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Item</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>SelectedText</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>SelectedIndex</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
                <Property>
                    <Name>Complete</Name>
                    <Value></Value>
                    <IsEnable>true</IsEnable>
                </Property>
            </Info>
        </x:XData>
    </XmlDataProvider>

Thanks again for your contribution! José Tavares

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜