1

私は、WPF アプリケーションでラベル、ボタン、テキストボックスの動的生成に取り組んでいました。私はそれらを動的に作成することに成功しましたが、1 つの大きな問題に直面しています。

Xaml:

<ListBox x:Name="myViewChannelList" HorizontalAlignment="Stretch" Height="Auto" ItemsSource="{Binding}" Margin="0" VerticalAlignment="Stretch" Width="Auto">
            <ListBox.ItemTemplate>
                <DataTemplate >
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="170" />
                            <ColumnDefinition />                                
                        </Grid.ColumnDefinitions>

                        <Label Grid.Column="0" Content="{Binding Path=ChanelName}" Margin="50,20,0,0"></Label>

                        <Grid Grid.Column="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <TextBox Grid.Column="0" Text="{Binding Path=VoltageText}" Height="25" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
                            <Button Grid.Column="1" Content="Set" Height="25" Command="{Binding ElementName=myViewChannelList, Path=DataContext.SetCommand}" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" ></Button>
                        </Grid>                            
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
</ListBox>

モデル クラス:

private string _ChanelName = "";
public String ChanelName
    {
        get
        {
            return _ChanelName;
        }

        set
        {
            if (value != _ChanelName)
            {
                _ChanelName = value;
                OnPropertyChanged("ChanelName");                    
            }
        }            
    }

    // Constructor
    public VoltageModel(string ChanelName)
    {
        this.ChanelName = ChanelName;            
    }

    public override string ToString()
    {
        return _ChanelName;
    }

ViewModel クラス:

class ChannelList : ObservableCollection<VoltageModel>, INotifyPropertyChanged
{
   private string _VoltageText;
    public string VoltageText
    {
        get { return _VoltageText; }
        set
        {
            _VoltageText = value;
            OnPropertyChanged("VoltageText");
        }
    }       

    // Method gets called when Set Button Is Clicked
    public void SetCommandExecuted()
    {
        string val = VoltageText;
    }

    //Notify Property Changed members are present
}

Xaml.cs クラス:

ChannelList myChanels = new ChannelList();                        

public VoltageView() // Constructor
{
     InitializeComponent();            
     myChanels.Add(new VoltageModel("VDD__Main"));
     myChanels.Add(new VoltageModel("VDD__IO__AUD"));
     myChanels.Add(new VoltageModel("VDD__CODEC__AUD"));                      
     myViewChannelList.DataContext = myChanels;            
}  

これにより、アプリケーションを実行すると、3 つのラベル (上記のコンテンツ)、3 つのテキストボックス、および 3 つのボタンが得られます。

テキストボックス内に値を入力すると、SetCommandExecuted() にブレークポイントを設定すると、ボタンのクリック時に null が表示されます。最も重要なことは、クリックした 4 つのボタンのいずれかがイベントを生成することです。最初のテキストボックスと最初のボタンを同期(バインド)し、2番目のテキストボックスと2番目のボタンを同期するなどです。基本的に、各コントロールは、行内の他のコントロールと同期している必要があります。他の行には影響しません。出来ますか???

4

2 に答える 2

3

これがあなたの質問に対する解決策です。一般的な慣例として、コードビハインドですべてのロジック、データの構築などを避けたいと考えています。すべてのビジネス ロジックは、単体テストを容易にするビュー モデルに含める必要があります。

これがビューです

.xaml

<StackPanel>
    <ListBox HorizontalAlignment="Stretch" 
             Height="Auto" 
             ItemsSource="{Binding VoltageCollection}"
             VerticalAlignment="Stretch" 
             Width="Auto">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Width="100" 
                           Content="{Binding ChannelName}" />
                    <TextBox Width="100" 
                             Text="{Binding VoltageText}" />
                    <Button Margin="10,0,0,0" 
                            Content="Set" 
                            Command="{Binding VoltageCommand}" 
                            CommandParameter="{Binding VoltageText}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

これがコードビハインドです

.xaml.cs

    private ChannelListViewModel m_voltageViewModel;
    public MainWindow()
    {
        InitializeComponent();

        m_voltageViewModel = new ChannelListViewModel();
        m_voltageViewModel.Initialize();

        DataContext = m_voltageViewModel;
    }

ここにモデルがあります: VoltageModel

public class VoltageModel : INotifyPropertyChanged
{
    public string ChannelName { get; set; }

    private string m_voltageText;
    public string VoltageText
    {
        get { return m_voltageText; }
        set 
        { 
            m_voltageText = value;
            OnPropertyChanged("VoltageText");
        }
    }

    public ICommand VoltageCommand { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

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

ビューモデルは次のとおりです。

public class ChannelListViewModel
{
    private ICommand m_voltageCommand;
    public ChannelListViewModel()
    {
        m_voltageCommand = new DelegateCommand(x => SetCommandExecute(x));
    }

    public void Initialize()
    {
        VoltageCollection = new ObservableCollection<VoltageModel> { new VoltageModel() { ChannelName = "VDD__Main", VoltageText = String.Empty, VoltageCommand = m_voltageCommand },
                                                                     new VoltageModel() { ChannelName = "VDD__IO__AUD", VoltageText = String.Empty, VoltageCommand = m_voltageCommand },
                                                                     new VoltageModel() { ChannelName = "VDD__CODEC__AUD", VoltageText = String.Empty, VoltageCommand = m_voltageCommand }};
    }

    public ObservableCollection<VoltageModel> VoltageCollection { get; set; }

    public void SetCommandExecute(object voltageText)
    {
        Debug.WriteLine(voltageText);
    }
}

最後に単純な DelegateCommand クラスのDelegateCommand

public class DelegateCommand : ICommand
{
    Action<object> m_executeDelegate;

    public DelegateCommand(Action<object> executeDelegate)
    {
        m_executeDelegate = executeDelegate;
    }

    public void Execute(object parameter)
    {
        m_executeDelegate(parameter);
    }

    public bool CanExecute(object parameter) { return true; }
    public event EventHandler CanExecuteChanged;
}

スクリーンショット 実行中

于 2012-10-11T05:04:15.623 に答える
0

一般的に非常に間違っている2つのことを認識したため、何が間違っていたのかについてはあまり知りませんでした。それらは、あなたの予期しない動作の問題である可能性があります。

1 つ目: DataTemplate はコントロールを上下に配置します。

修理 :

     <DataTemplate >
            <Grid>
                <Grid.ColumnDefinitions>
                     <ColumnDefinition />
                     <ColumnDefinition />
                     <ColumnDefinition />
                </Grid.ColumnDefinitions>

                <Label Grid.Column="0" Content="{Binding Path=ChanelName}" />
                <TextBox Grid.Column="1" Text="{Binding Path=VoltageText}" />
                <Button Grid.Column="2" Command="{Binding ElementName=myViewChannelList, Path=DataContext.SetCommand}" />
            </Grid>
        </DataTemplate>

2 番目: PropertyChanged イベントが発生した後にプロパティが設定されるため、次に値を入力するまで更新されません。

修理 :

private T _property;
public T Property
{
    get { return _property; }
    set
    {
        _property = value;
        OnPropertyChanged("Property");
    }
}           

これらの修正を行い、まだ問題がある場合は投稿を編集して、私の回答の下にコメントを投稿してください。

于 2012-10-10T06:17:58.277 に答える