我有一个ListBox,上面有几个项目(TextBlocks,Images等),我想要做的是通过它在特定ListBox索引的名称访问一个元素。
我知道我需要访问的元素名称和索引,在这种情况下,我需要将图像控件的visibility属性更改为折叠。
我查看了一些使用VisualTreeHelper
here的示例,但它们只是按名称访问元素,而不是按名称和索引访问,这是我需要做但却无法访问的到。
谢谢,鲍勃。
答案 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
希望将来帮助其他人......