Microsoft Silverlight在线文件存储系统动态生成按钮技术求助
Hey Daniel, let's work through this problem you're facing—generating dynamic buttons/links for user files on load is a super common scenario in Silverlight, and we've got two reliable ways to make it happen.
Approach 1: Dynamically Create Controls in C# Code-Behind
If you want a straightforward, quick implementation, you can create and add buttons directly in your C# code. Here's how:
Step 1: Add a Container in XAML
First, place a layout container (like StackPanel or WrapPanel) in your XAML to hold the dynamic buttons. Give it a name so you can reference it in code:
<StackPanel x:Name="fileContainer" Orientation="Vertical" Margin="10" />
Step 2: Generate Buttons in Code-Behind
In your page's code-behind, fetch the user's file list, loop through each file, create a button/hyperlink, and add it to the container:
// Assume you have a method that retrieves the user's files (e.g., List<FileInfo> userFiles) private void LoadUserFiles() { var userFiles = GetUserDirectoryFiles(); // Replace with your actual file retrieval logic foreach (var file in userFiles) { // Use HyperlinkButton for link-style UI, or Button for a standard button var fileLink = new HyperlinkButton(); fileLink.Content = file.Name; fileLink.Tag = file; // Store the file object for easy access on click fileLink.Click += FileLink_Click; fileLink.Margin = new Thickness(0, 5, 0, 0); // Add spacing between items // Make sure we're on the UI thread (critical if fetching files asynchronously) Dispatcher.BeginInvoke(() => fileContainer.Children.Add(fileLink)); } } // Handle the button click event private void FileLink_Click(object sender, RoutedEventArgs e) { var clickedLink = sender as HyperlinkButton; var selectedFile = clickedLink.Tag as FileInfo; // Add your file action logic here (e.g., download, open preview) MessageBox.Show($"You selected: {selectedFile.Name}"); }
Approach 2: Use ItemsControl for Data-Bound, OOP-Friendly UI (Recommended)
For a more scalable, maintainable solution (aligned with OOP and MVVM principles), use ItemsControl to bind your file data to the UI. This way, you don't manually manipulate controls—your data drives the UI.
Step 1: Create a File View Model
First, define a simple view model class to represent your files (this is the OOP part):
public class FileViewModel : INotifyPropertyChanged { private string _fileName; public string FileName { get => _fileName; set { _fileName = value; OnPropertyChanged(nameof(FileName)); } } // Add other properties like file size, path, etc., as needed public ICommand FileActionCommand { get; set; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // Simple RelayCommand implementation (Silverlight doesn't include this by default) public class RelayCommand : ICommand { private readonly Action _execute; public RelayCommand(Action execute) => _execute = execute; public bool CanExecute(object parameter) => true; public void Execute(object parameter) => _execute(); public event EventHandler CanExecuteChanged; }
Step 2: Set Up Data Collection in Your Page
In your page's code-behind (or view model if using MVVM), create an ObservableCollection to hold your file view models. This collection automatically updates the UI when items are added/removed:
public ObservableCollection<FileViewModel> UserFiles { get; set; } public MainPage() { InitializeComponent(); UserFiles = new ObservableCollection<FileViewModel>(); LoadUserFilesToCollection(); this.DataContext = this; // Bind the page to itself (or use a separate view model) } private void LoadUserFilesToCollection() { var userFiles = GetUserDirectoryFiles(); foreach (var file in userFiles) { UserFiles.Add(new FileViewModel { FileName = file.Name, FileActionCommand = new RelayCommand(() => HandleFileAction(file)) }); } } private void HandleFileAction(FileInfo file) { // Your file logic here MessageBox.Show($"Processing file: {file.Name}"); }
Step 3: Bind to ItemsControl in XAML
Finally, use ItemsControl in XAML to render each file as a button/hyperlink. You can customize the layout and template easily:
<ItemsControl ItemsSource="{Binding UserFiles}"> <!-- Define how each file item looks --> <ItemsControl.ItemTemplate> <DataTemplate> <HyperlinkButton Content="{Binding FileName}" Command="{Binding FileActionCommand}" Margin="5" FontSize="12"/> </DataTemplate> </ItemsControl.ItemTemplate> <!-- Optional: Change layout to horizontal wrapping instead of vertical --> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl>
Key Notes
- UI Thread Warning: If you're fetching files asynchronously (e.g., from a web service), always use
Dispatcher.BeginInvokewhen modifying UI elements (like adding buttons to the container). - Choose Control Type: Use
HyperlinkButtonfor a link-like appearance, orButtonfor a standard button—both work with either approach. - Scalability: The
ItemsControlmethod is better for long-term maintenance, especially if you plan to add features like file filtering, sorting, or dynamic updates to the file list.
Either of these methods should solve your problem. Start with the code-behind approach for a quick fix, or go with the data-bound ItemsControl method for a more robust, OOP-aligned solution.
内容的提问来源于stack exchange,提问作者Daniel Stewart

