如何在特定的ListBox索引中按名称访问元素

时间:2014-03-03 01:42:44

标签: c# wpf visual-studio-2012 windows-phone-8 listbox

我有一个ListBox,上面有几个项目(TextBlocks,Images等),我想要做的是通过它在特定ListBox索引的名称访问一个元素。

我知道我需要访问的元素名称和索引,在这种情况下,我需要将图像控件的visibility属性更改为折叠。

我查看了一些使用VisualTreeHelper here的示例,但它们只是按名称访问元素,而不是按名称和索引访问,这是我需要做但却无法访问的到。

谢谢,鲍勃。

2 个答案:

答案 0 :(得分:2)

我实现了一个小型演示来强调使用MVVM patern的数据绑定。 在此示例中,我通过取消/检查TextBlock,使用绑定到TextBlock.Visibility的ShowTextbox属性切换Checkbox可见性。

App.xaml.cs

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var mainViewModel = new MainViewModel
        {
            ListItems = new ObservableCollection<MyModel>
            {
                new MyModel
                {
                    MyPropertyText = "hello",
                    ShowText = true,
                    ShowTextbox = Visibility.Visible
                }
            }
        };
        var app = new MainWindow() {DataContext = mainViewModel};
        app.Show();
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wpfApplication1="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox HorizontalAlignment="Left" Height="148" VerticalAlignment="Top" Width="299" Margin="30,57,0,0" ItemsSource="{Binding Path=ListItems}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Path=MyPropertyText}" Visibility="{Binding Path=ShowTextbox}"/>
                    <CheckBox IsChecked="{Binding ShowText}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

MainWindow.cs

public partial class MainWindow : Window
{

    private MainViewModel _mainViewModel;
    public MainWindow()
    {
        InitializeComponent();           

    }
}

MainViewModel.cs

public class MainViewModel : ObservableObject
{

    public ObservableCollection<MyModel> ListItems 
    { 
        get { return _listItems; }
        set
        {
            _listItems = value;
            RaisePropertyChanged("ListItems");
        }
    } 


}

MyModel.cs

public class MyModel : ObservableObject
{
    private string _myPropertyText;
    private bool _showText;
    private Visibility _showTextbox;

    public string MyPropertyText
    {
        get { return _myPropertyText; }
        set
        {
            _myPropertyText = value;
            RaisePropertyChanged("MyPropertyText");
        }
    }

    public bool ShowText
    {
        get { return _showText; }
        set
        {
            _showText = value;
            RaisePropertyChanged("ShowText");
            ShowTextbox = value ? Visibility.Visible : Visibility.Collapsed;
        }
    }

    public Visibility ShowTextbox
    {
        get { return _showTextbox; }
        set
        {
            _showTextbox = value;
            RaisePropertyChanged("ShowTextbox");
        }
    }
}

ObservableObject.cs

public class ObservableObject : INotifyPropertyChanged
{
    #region Constructor

    public ObservableObject() { }

    #endregion // Constructor

    #region RaisePropertyChanged

    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void RaisePropertyChanged(string propertyName = "")
    {
        VerifyPropertyName(propertyName);

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion

    #region Debugging Aides

    /// <summary>
    /// Warns the developer if this object does not have
    /// a public property with the specified name. This 
    /// method does not exist in a Release build.
    /// </summary>
    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // If you raise PropertyChanged and do not specify a property name,
        // all properties on the object are considered to be changed by the binding system.
        if (String.IsNullOrEmpty(propertyName))
            return;

        // Verify that the property name matches a real,  
        // public, instance property on this object.
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
                throw new ArgumentException(msg);
            else
                Debug.Fail(msg);
        }
    }

    /// <summary>
    /// Returns whether an exception is thrown, or if a Debug.Fail() is used
    /// when an invalid property name is passed to the VerifyPropertyName method.
    /// The default value is false, but subclasses used by unit tests might 
    /// override this property's getter to return true.
    /// </summary>
    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

    #endregion // Debugging Aides

    #region INotifyPropertyChanged Members

    /// <summary>
    /// Raised when a property on this object has a new value.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    #endregion // INotifyPropertyChanged Members

}

答案 1 :(得分:0)

我最终以稍微不同的方式进行了讨论,基于找到here的示例并使用了元素'tag属性,只需将元素从TextBlock更改为{{1 }}

这样我可以绑定元素Tag,稍后再使用它来定位所需的项目。

Image

希望将来帮助其他人......