1

了解しました。私はC++開発者であり、現在WPFアプリに取り組んでいますが、これは難しい状況のようです。テキストボックスとボタンの両方が相互にバインドされているボタン、ラベルなどのセットを動的に生成しました。以前はC++コードでこれを行っていましたが、今はWPFアプリで行う必要があります。

XAML:

<ListBox x:Name="myViewChannelList" HorizontalAlignment="Stretch" Height="Auto" ItemsSource="{Binding VoltageCollection}" Margin="0" VerticalAlignment="Stretch" Width="Auto" >
            <ListBox.Resources>
                <convert:BooleanToVisibilityConverter x:Key="booltovisibility"/>
            </ListBox.Resources>

            <ListBox.ItemTemplate>
                <DataTemplate >
                    <Grid Visibility="{Binding IsAvailable, Converter={StaticResource booltovisibility}}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="170"  />
                            <ColumnDefinition />
                            <ColumnDefinition  />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>

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

                        <Grid Grid.Column="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <TextBox Grid.Column="0" Text="{Binding VoltageText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="25" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="170,20,0,0" />
                            <Button Grid.Column="1" Content="Set" Height="25" CommandParameter="{Binding VoltageText}" Command="{Binding VoltageCommand}" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,20,0,0" ></Button>
                        </Grid>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

ViewModel:

private ICommand m_voltageCommand;

    public ChannelList()
    {
         m_voltageCommand = new DelegateVoltageCommand(x => SetCommandExecute(x));
    }

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

ObservableCollection<VoltageModel> _voltages;
public ObservableCollection<VoltageModel> VoltageCollection
{
    get
    {
        return _voltages;
    }
    set
    {
        _voltages = value;
        OnPropertyChanged("VoltageCollection");
    }
} 

// Event when SET Button is clicked
public void SetCommandExecute(object voltageText)
{       
    string value = voltageText.ToString();
    int val = Convert.ToInt32(value);
}

したがって、メソッドに示すように、ボタン+テキストボックス+ラベルを3回生成しInitialize()ます。VoltageCommand = m_voltageCommandこれで、テキストボックスに入力されたテキストが表示され、ボルテージテキストが入力されSetCommandExecute(object voltageText)た値を表示するメソッドが呼び出されます。

モデル:

string voltageText = string.Empty;
    public string VoltageText
    {
        get
        {
            return voltageText;
        }

        set
        {
            voltageText = value;
            OnPropertyChanged("VoltageText");
        }
    }

**C++ Code:**

// Since we have 3 channels, channel maintains count
if(button == m_setButton[channel])
{
    unsigned cmd = 0x0300;
    int numBytes = 0;

    cmd |= (channel & 0xFF);
            // Some code

ここでは、どのボタンがクリックされたかをユーザーに通知し、lの値を取ります。channeつまり、2番目のボタンがクリックされた場合はchannel = 2

ここでは、C++1で記述されたコードを実装する必要があります。チャンネル、つまりどのボタンがクリックされたかを取得するにはどうすればよいですか。見てくださいcmd |= (channel & 0xFF);、それはchannel値を使用しました。アプリでそれを達成するにはどうすればよいですか?

4

5 に答える 5

2

単純にIDプロパティをVoltageBoardChannelクラスに追加できます。

int index ; 
public int ID 
{ 
    get 
    { 
        return index; 
    } 

    set 
    { 
        index = value; 
        OnPropertyChanged("ID"); 
    }
}

次に、CommandParameter Bindingをに変更すると、テキストだけでなく、IDを保持するVoltageBoardChannelクラスのインスタンスも受信するようになりますCommandParameter="{Binding}"CommandParameter="{Binding VoltageText}"

コマンドExecuteメソッドで

public void DoSomethingExecute(object param) 
{ 
    VoltageBoardChannel result = param as VoltageBoardChannel; 
    string value = result.VoltageText;
    int index = result.ID;
}
于 2012-10-16T09:45:42.747 に答える
1

MVVMの実装に関する基本的な問題は次のとおりです。

ViewModelはビューについて決して知る必要はありません。ビュー要素から独立してテスト可能である必要があります

SetCommandExecuteメソッドでは、ビューから送信された作業ベースのテキストを実行することを期待しています。ViewModelの他の部分からの情報のみを使用して、SetCommandExecuteメソッドの単体テストを作成する場合、何を渡しますか?

代わりに、SecCommandExecuteは次のようになります。

SetCommandExecute(object voltageModel)
{
    VoltageModel myModel = voltageModel as VoltageModel; // Cast the model to the correct object type
    if (myModel != null)
    { // myModel will be null of voltageModel is not a VoltageModel instance
        // TODO: Whatever work you need to do based on the values of the myModel
    }
}

XMLは次のようになります。

<Button Grid.Column="1" Content="Set" Height="25" CommandParameter="{Binding }" Command="{Binding VoltageCommand}" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,20,0,0" ></Button>

これはどのように作動しますか?それはDataContextに帰着します。グリッド内の各ラインのDataContextはVoltageModelであるため、そのプロパティのいくつかに直接バインドできます。例Text="{Binding VoltageText ...}"

データグリッドの各アイテムには、各行のオブジェクトインスタンスの暗黙のDataContextがあります。各行はVoltageModelのインスタンスにバインドされているため、その事実をコードで直接使用できます。ビューは、操作しているViewModelのプロパティとインスタンスを認識しており、ユーザーが操作した特定のVoltageModelをViewModelに「ダウン」で渡すことができます。

理由:

コマンドイベントが実行されると、VoltageModelオブジェクトを渡す必要があります。これにより、すべてのインスタンスプロパティに直接アクセスできます。SetCommandExecuteビューがテキストをパスしたり、解析したり、ビューのコントロールを見つけたりすることなく、メソッドを単体テストできるようにするため、これがベストプラクティスであることを忘れないでください。

つまり、ViewModelは完全に自己完結型であり、ViewModelだけで利用可能なデータに基づいてすべての単体テストを実行できる必要があります。

于 2012-10-15T19:19:34.827 に答える
0

私は自分で少しだけWPFを実行しました。データをコントロールにバインドしたとき、そのデータ項目を他のデータ項目と一意に区別する方法がありました。

擬似コード:

private void Button_Clicked(object sender, EventArgs e) {
  MyType obj = (MyType)listView1.SelectedItem[0];
  if (obj.UniqueItem == whatINeed) {
    DoStuffFunction();
  }
}

それがあなたのケースでうまくいくかどうかはわかりませんが、それが私の問題に取り組んだ方法でした。

于 2012-10-15T17:38:19.667 に答える
0

すでに電圧テキストボックスをプロパティにバインドしているので、コマンドパラメータとしてその値を渡す必要はありません。代わりに、ソースをコマンドとして指定できます。

<Button CommandParameter="TheButton" />

そして、コマンドハンドラーの実装では:

public void SetCommandExecute(object source)
{       
    string source = source as string;

    if (source == "TheButton")
    {
       int val = Convert.ToInt32(this.VoltageText);
    }
}
于 2012-10-15T17:43:06.877 に答える
0

こんにちはVoltageTextをCommandParameterにバインドする代わりに、Buttonをそれにバインドすると、ButtonDataContextからVoltageTextを取得するか、ListBoxのSelectedItemをViewModelプロパティにバインドすることができます。これが役立つことを願っています。

<ListBox x:Name="lb">
        <ListBoxItem>
            <Button x:Name="btn" CommandParameter="btn" Command="{Binding MyCommand}" VerticalAlignment="Bottom" Height="30"/>
        </ListBoxItem>
        <ListBoxItem>
            <Button  CommandParameter="{Binding SelectedIndex, ElementName=lb}" Command="{Binding MyCommand}" VerticalAlignment="Bottom" Height="30"/> 
        </ListBoxItem>
    </ListBox>

 public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
    private ICommand _myCommand;
    public ICommand MyCommand { get { return _myCommand ?? (new CommandHandler((o) => FireCommand(o),()=> true)); } }
    public void FireCommand(object obj)
    {
        var a = lb.SelectedIndex; 
    }

public class CommandHandler:ICommand
{
        private Action<object> del;
        public CommandHandler(Action<object> action, Func<bool> b=null)
        {
            del = action;
        }

        #region ICommand Members

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

        public event EventHandler CanExecuteChanged;

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

        #endregion
}

上記の2つの方法のいずれかを試すことができます。

于 2012-10-15T17:46:34.583 に答える