2016-10-26 28 views
0

私のテキストブロックが更新されていません。 ViewModelでテキストブロックを更新すると、バインディングが正しいように見えます。私は問題が私がモデルでそれを更新する方法だと信じていますが、良いMVVM戦略であるかどうかわからない値を渡すので、なぜ私のobservableCollectionだけが更新されるのかわかりません。モデルでプロパティが変更されたときにテキストブロックが更新されない

XAML部分:

<Grid> 
    <TextBox x:Name="NewLabelBx" HorizontalAlignment="Left" Height="23" Margin="54,449,0,0" TextWrapping="Wrap" Text="{Binding NewLabel,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="314"/> 
    <Button x:Name="NewLabelBtn" Content="Add Label" HorizontalAlignment="Left" Margin="293,490,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.518,-0.709" Command="{Binding Path=NewLabelBtn}" /> 
    <TextBlock x:Name="FilesProcessedBlck" HorizontalAlignment="Left" Margin="54,507,0,0" TextWrapping="Wrap" Text="{Binding FilesProcessedBlck, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" RenderTransformOrigin="-0.7,0.562" Width="65"/> 
</Grid> 

のViewModel部分:

public class P4LabelBatteryViewModel : BindableBase 
{ 
    private P4LabelBatteryModel p4LabelBatteryModel = new P4LabelBatteryModel(); 

    public P4LabelBatteryViewModel() 
    { 
     P4LabelBatteryModel p4LabelBatteryModel = new P4LabelBatteryModel(); 

     this.GetBatteryBtn = new DelegateCommand(chooseFile, canChooseFile); 
     this.NewLabelBtn = new DelegateCommand(chooseNewLabel, canNewLabel).ObservesProperty(() => NewLabel); 
     this.FilesProcessedBlck = 2; //this works. 
    } 

    //other code here 

    private void chooseNewLabel() 
    { 
     if (ScriptCollection.Count > 0) 
     { 
      ScriptCollection = P4LabelBatteryModel.TagsFilesModel(NewLabel, ScriptCollection); 
     } 
    } 


    private int _filesProcessedBlck; 
    public int FilesProcessedBlck 
    { 
     get 
     { 
      return _filesProcessedBlck; 
     } 
     set 
     { 
      SetProperty(ref _filesProcessedBlck, value); 
     } 

    } 

    private ObservableCollection<ScriptModel> _scriptCollection = new ObservableCollection<ScriptModel>(); 
    public ObservableCollection<ScriptModel> ScriptCollection 
    { 
     get 
     { 
      return _scriptCollection; 
     } 
     set 
     { 
      SetProperty(ref _scriptCollection, value); 
     } 

    }   

} 

モデル部分:

class P4LabelBatteryModel 
{ 

    public static ObservableCollection<ScriptModel> TagsFilesModel(string NewLabel, ObservableCollection<ScriptModel> observableCollection) 
    { 
     string newLabel = NewLabel; 
     var scriptsToTagColl = observableCollection; 
     string[] files = null; 

     var _p4LabelBatteryViewModel = new P4LabelBatteryViewModel(); 
     _p4LabelBatteryViewModel.FilesProcessedBlck++; //xaml is never updated with this value. 

     //This will generate an IPC when returned 
     ObservableCollection<ScriptModel> newCollection = new ObservableCollection<ScriptModel>(); 

     //code here that modifies newCollection xaml updates when this returns, _p4LabelBatteryViewModel.FilesProcessedBlck++; does not. 

     return newCollection; 
    } 
} 

私は、デバッガを実行すると、私はP4LabelBatteryViewModel.FilesProcessedBlckが変更されて見ることができますが、 XAMLが更新されていません。

+0

あなたの '.DataContext'に問題があるように見えます。 'ObservableCollection'コードで2番目のインスタンスを作成している間は、TextBlockが' P4LabelBatteryViewModel'の1つのインスタンスを指しているように、正しく割り当てられていないようです。 – Rachel

答えて

1
var _p4LabelBatteryViewModel = new P4LabelBatteryViewModel(); 
    _p4LabelBatteryViewModel.FilesProcessedBlck++; //xaml is never updated with this value. 

OKというTextBlockは今まであなたが最初の場所で何を期待表示されている場合、ので、あなたのXAMLは、のviewmodelのコピーを持っている必要があります。しかし、このメソッドでは、同じviewmodelクラスの新しいインスタンスを作成し、そこにプロパティを設定してから、それ以外は何も行いません。それは範囲外になり、最終的にガベージコレクタがそれを食べる。任意のビューのDataContextはどこにもないので、もちろんUIには影響しません。

_p4LabelBatteryViewModelはローカル変数です。その方法の外の誰もそれを見たり、それが存在することを知ることさえありません。実際にUIに表示されているビューモデルのコピーを変更する場合は、のインスタンスを変更する必要があります。また、ローカル変数の先頭に_を付けないでください。慣例により、先頭のアンダースコアはクラスに属するプライベートフィールドを示します。混乱を避けるために、この条約を守ることが最善です。

viewmodelは、独自のFilesProcessedBlckプロパティを更新する必要があります。どのような場合でも、モデルがビューモデルの状態を維持する責任を負うことはお勧めできません。それはビューモデルの問題です、彼はそれに対処してください。

private void chooseNewLabel() 
{ 
    if (ScriptCollection.Count > 0) 
    { 
     ScriptCollection = P4LabelBatteryModel.TagsFilesModel(NewLabel, ScriptCollection); 
     ++FilesProcessedBlck; 
    } 
} 

とモデルで...

public static ObservableCollection<ScriptModel> TagsFilesModel(string NewLabel, IList<ScriptModel> scriptsToTagColl) 
{ 
    string newLabel = NewLabel; 
    string[] files = null; 

    // This will generate an IPC when returned 
    ObservableCollection<ScriptModel> newCollection = new ObservableCollection<ScriptModel>(); 

    //code here that modifies newCollection xaml updates when this returns, _p4LabelBatteryViewModel.FilesProcessedBlck++; does not. 

    return newCollection; 
} 

私はTagsFilesModelを簡素化するために、他のマイナーな変更のカップルを作りました。たとえば、発信者にObservableCollection<T>を渡す必要はありません。他に何かを与える理由は決してないかもしれませんが、あなたのコードにこのような柔軟性を持たせるならば、それは報われます。

もう1つの項目。これは無害ですが、価値を知っ:

<TextBlock 
    x:Name="FilesProcessedBlck" 
    HorizontalAlignment="Left" 
    Margin="54,507,0,0" 
    TextWrapping="Wrap" 
    Text="{Binding FilesProcessedBlck}" 
    VerticalAlignment="Top" 
    RenderTransformOrigin="-0.7,0.562" 
    Width="65" 
    /> 

UpdateSourceTrigger=PropertyChanged

はその Bindingに任意の目的を果たしていません。バインディングの「ソース」はviewmodelプロパティです。 「ターゲット」はUIコントロールプロパティです。 UpdateSourceTrigger=PropertyChangedは、 Bindingに、コントロールプロパティが変更されるたびにviewmodelプロパティを更新するように指示します。それはばかげているようですが、 UpdateSourceTrigger=LostFocusに設定することもできます。 TextBox.Textのデフォルト値は LostFocusです。普通のケースは TextBoxですが、ユーザーはしばらく入力していますが、入力を終了して別のコントロールにフォーカスを変更するまでは、ビューモデルの更新は気にしません。viewmodelプロパティを更新すると多くの副作用が発生する可能性があるので、 Textが変更されるたびにバインドされたviewmodelプロパティを更新すると、病的な動作に終わることがあります。ユーザーが文字を入力するたびに、動きに投げ込まれるので、UIが駄目になる。従って LostFocus

これは、TextBoxではないので、この質問の話題はすべてオフです。 TextBlockです。ソースプロパティをまったく更新できないため、フラグは無効です。

ところで、 "Blck"とはどういう意味ですか?それはTextBlockに表示されているからですか? UIに表示されている別の場所を追加すると、新しい場所が表示されます。名前を変更してFilesProcessedBlckAndLblにする必要がありますか?それをFilesProcessedCountと呼んで、UIが何をしているかを気にすることなく、ビューモデルをビジネスから離しておくことをお勧めします。

+0

エド、助けをありがとう。 "Blck"は、私が働いていた場所での命名規則からのブロックです。私は "No code behind"を使用しようとしていましたが、遠くまで持ち歩いていたかもしれません。モデルでは、いくつのアイテムが処理されたかをカウントするループがあり、ViewModelに戻る前にそのモデル(FilesProcessedBlck)をモデルから更新しようとしていました。 – coolercargo

関連する問題