2012-01-10 2 views
0

У меня есть настраиваемый контроль, который нужно добавить столько раз, когда вы нажимаете кнопку. Это должно произойти из шаблона MVVM WPF. Я вставил свой код здесь. Будет здорово, если вы, ребята, можете помочь в этом.Добавить пользовательский элемент управления в стеке с помощью Viewmodel WPF

Пожалуйста, помогите мне

<Window x:Class="DOCS_APP_ELEMENT.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:usercontrol="clr-namespace:DOCS_APP_ELEMENT" 
    xmlns:viewModel="clr-namespace:DOCS_APP_ELEMENT.ViewModels" 
    Title="MainWindow" Height="350" Width="400"> 
<Grid Margin="10" Name="myGrid"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"></RowDefinition> 
     <RowDefinition Height="Auto"></RowDefinition> 
     <RowDefinition Height="Auto"></RowDefinition> 
    </Grid.RowDefinitions> 
    <Border CornerRadius="5" BorderBrush="SteelBlue" BorderThickness="2" Grid.Row="0"> 
     <StackPanel Orientation="Vertical"> 
      <StackPanel Orientation="Horizontal"> 
       <Label Content="Type:" Margin="20,0,4,0"></Label> 
       <ComboBox Name="cmbQuestionType" Width="300" Style="{Binding ComboBoxStyle}" Margin="0,5,0,5" IsEnabled="False">     </ComboBox> 
      </StackPanel> 
      <StackPanel Orientation="Horizontal" Margin="0,5,0,5"> 
       <Label Content="Question:" Margin="0,0,4,0"></Label> 
       <TextBox Name="txtQuestion" Width="300" Height="50" Margin="0,2,0,0" AcceptsReturn="True"></TextBox> 
      </StackPanel> 
      <StackPanel Orientation="Horizontal" Margin="0,5,0,5" > 
       <Label Content="Answer:" Margin="7,0,4,0"></Label> 
       <TextBox Name="txtAnswer" Style="{StaticResource TextboxStyle}" Margin="0,2,0,0"></TextBox> 
      </StackPanel> 
     </StackPanel> 
    </Border> 
    <Border CornerRadius="5" BorderBrush="SteelBlue" BorderThickness="2" Grid.Row="1" Margin="0,10,0,0" > 
     <ScrollViewer VerticalScrollBarVisibility="Auto" Height="100"> 
     <StackPanel Name="myCustom" Orientation="Vertical" > 
       **<!--<ADD CUSTOM CONTROl HERE>-->** 
      </StackPanel> 
     </ScrollViewer> 
    </Border> 
    <Border CornerRadius="5" BorderBrush="SteelBlue" BorderThickness="2" Grid.Row="2" Margin="0,10,0,0"> 
     <Border.DataContext> 
      <viewModel:ViewElements/>      
     </Border.DataContext> 
     <Button Name="btnAdd" Content="Add" DataContext="{Binding }" Command="{Binding Path=AddInstace}"></Button> 
    </Border> 
</Grid> 

+0

Вам нужно только добавить элементы управления или вы собираетесь представить данные в элементе управления? Если это так, я предлагаю использовать ItemsControl en datatemplates. –

+0

Я собираюсь добавить новый настраиваемый элемент управления здесь. Пользовательский элемент управления будет содержать несколько других элементов управления. –

+0

Я думаю, что предоставленные ответы будут вам очень полезными –

ответ

6

Я хотел бы сделать это следующим образом:

имеют ObservableCollection<CustomClass> в вашем ViewModel. Представление вашего CustomClass - это DataTemplate с указанным выше разметкой.

Вот полный рабочий пример:

<Grid> 
    <Grid.DataContext> 
     <local:MyViewModel></local:MyViewModel> 
    </Grid.DataContext> 
     <StackPanel> 
     <ScrollViewer VerticalScrollBarVisibility="Auto" Height="200"> 
     <ItemsControl ItemsSource="{Binding CustomControls}"> 
      <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Border Background="Green"> 
       <StackPanel> 
        <TextBlock Text="I am a Custom Control"></TextBlock> 
        <TextBlock Text="{Binding DisplayValue}"></TextBlock> 
       </StackPanel> 
       </Border> 
      </DataTemplate> 
      </ItemsControl.ItemTemplate> 
      <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel/> 
      </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      </ItemsControl> 
     </ScrollViewer> 
     <Button Width="200" Height="50" Command="{Binding AddControlCommand}">Add Control</Button> 
     <Button Width="200" Height="50" Command="{Binding RemoveControlCommand}">Remove Control</Button> 
    </StackPanel> 
    </Grid> 

ViewModel:

public abstract class ViewModel : INotifyPropertyChanged 
    { 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    } 

    public class RelayCommand : ICommand 
    { 
    ... look that up yourself if you don't have a derived command class yet in your project... 
    } 

    public class MyViewModel : ViewModel 
    { 
    public ICommand AddControlCommand 
    { 
     get 
     { 
     return new RelayCommand(x=>this.AddControl()); 
     } 
    } 

    public ICommand RemoveControlCommand 
    { 
     get 
     { 
     return new RelayCommand(x => this.RemoveControl()); 
     } 
    } 

    private void AddControl() 
    { 
     CustomControls.Add(new CustomControl() {DisplayValue = "newControl"}); 
    } 

    private void RemoveControl() 
    { 
     if (CustomControls.Count > 0) 
     { 
     CustomControls.Remove(CustomControls.Last()); 
     } 
    } 

    private ObservableCollection<CustomControl> _customControls; 

    public ObservableCollection<CustomControl> CustomControls 
    { 
     get 
     { 
     if (_customControls == null) 
     { 
     _customControls = new ObservableCollection<CustomControl>() 
       { 
        new CustomControl() {DisplayValue = "Control1"}, 
        new CustomControl() {DisplayValue = "Control2"}, 
        new CustomControl() {DisplayValue = "Control3"} 
       }; 
     } 
     return _customControls; 
     } 
    } 
    } 

    public class CustomControl : ViewModel 
    { 
    public string DisplayValue { get; set; } 
    } 
+0

Благодарим за ответ. Не могли бы вы построить небольшой образец. –

+0

В соответствии с запрошенной добавленной игрой. HTH – SvenG

+0

Эй, не могли бы вы дать мне свой идентификатор электронной почты. Поэтому я могу отправить файл своего решения, чтобы исправить мою проблему. –

4

Чтобы использовать шаблон MVVM вы будете нуждаться в ViewModel, что имеет список объектов данных, которые связаны с ваши пользовательские элементы управления. Эти элементы управления могут быть сгенерированы элементом ItemsControl. Поскольку я не знаю ваших данных, я могу просто дать вам общий пример.

MainWindow.xaml (Просмотр)

<ItemsControl ItemsSource="{Binding DataList}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <!-- instead of the TextBlock you would use your control --> 
      <TextBlock Text="{Binding}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

MainWindow.xaml.cs (Просмотр кода фоновым)

public MainWindow() 
{ 
    DataContext = new MainWindowViewModel(); 
    InitializeComponent(); 
} 

MainWindowViewModel.cs (ViewModel)

public class MainWindowViewModel 
{ 
    public ObservableCollection<string> DataList { get; set; } 

    public MainWindowViewModel() 
    { 
     DataList = new ObservableCollection<string> 
        { 
         "Data 1", 
         "Data 2", 
         "Data 3" 
        }; 
    } 
} 

Свойство Binding for the Text не имеет пути, поскольку DataContext здесь является строковым объектом DataList. Если вы используете сложные объекты, вам нужно использовать Путь к свойству объекта (например, Text={Binding Path=myProperty})

+0

Как подключить файл моего решения здесь. Так что вы, ребята, можете попробовать. –

+0

Я не думаю, что вы можете это сделать. Но я уверен, что наши решения будут работать. Просто попробуйте и спросите, что я где-то застрял. – MatthiasG

Смежные вопросы