我對此感到非常困惑,并進行了搜索,但找不到答案。我確定我沒有正確理解某些東西。你能向我解釋一下嗎?
我有一個視圖和一個視圖模型。在視圖中我有一個 Textblock
<TextBlock
Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
IsEnabled="{Binding Enable, Mode=OneWay}"
Margin="5,10,5,10">
<Run Text="File: "/>
<Run Text="{Binding FilePathName}"/>
</TextBlock>
在視圖的頂部我有
d:DataContext="{d:DesignInstance d:Type=viewModels:MainWindowViewModel}"
我還在后面的代碼中添加了
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
我不想在此處添加 DataContext,但起初似乎使它起作用,但現在我不確定我是否需要它,我將嘗試將其洗掉。
我想我明白這一部分,View 中的資料將從 ViewModel 中名為 FilePathName 的專案中重繪 。
現在在視圖模型中,我為 FilePathName 創建了“get and set”:
private string _filepathname;
public string FilePathName
{
get => _filepathname;
set
{
if (_filepathname != value)
{
_filepathname = value;
OnPropertyChanged();
}
}
}
現在這是我的理解必須變得有點模糊的地方。我認為在 ModelView 中我將只使用私有字串。這意味著當我像這樣改變它的值時:
_filepathname = “MyNewName”;
然后 PropertyChanged 將看到此更改并將通過公共 FilePathName 更新視圖。但是,如果我使用 FileOpenDialog 并打開一個檔案然后說
if (openFileDialog.FileName != "")
{
_filepathname = openFileDialog.FileName;
ProcessFile();
}
我在這里使用私人,但這永遠不會更新。如果我在“獲取和設定”中放置一個斷點,我們就永遠不會去那里,所以 UI 永遠不會更新。
但是在 ProcessFile() 我使用
StreamReader sr = new StreamReader(_filepathname);
我確實閱讀了正確的檔案。這我可以理解,因為它也是私人的。但是……如果我現在將私有更改為公共如下
if (openFileDialog.FileName != "")
{
FilePathName = openFileDialog.FileName;
ProcessFile();
}
我現在更新 UI 并打開正確的檔案進行閱讀。似乎有時我需要使用 private 有時需要使用 public 來使其作業。為什么?
第二個問題是為什么 isEnabled 似乎不適用于 TextBlock。我讓它處理按鈕和文本框。我在 TextBlock 中使用它如下,你可以在上面進一步看到它。
IsEnabled="{Binding Enable, Mode=OneWay}"
所有幫助表示贊賞。
uj5u.com熱心網友回復:
這不是那樣作業的。如果是,我們為什么需要屬性?
這:
myString = "new value"
只為變數賦值。就這樣。當您使用屬性執行此操作時,將呼叫屬性設定器,因此:
if(myString != value)
{
myString = value; //new value will be assigned to variable
OnPropertyChanged(); //property changed will be called
}
當您為變數賦值時,您就可以讀取它,這就是發生的事情。此變數稱為“支持欄位”。它在那里是因為必須有一些存盤值的變數。如果您像這樣宣告財產:
public string MyString {get; set;}
在幕后,編譯器還創建了這樣的支持欄位,最終它的作業方式如下:
string __myString;
public string MyString
{
get {return __myString;}
set {__myString = value;}
}
所以,正如你所看到的,這只是一種合成糖。如果你想從屬性中獲得更多(比如呼叫屬性改變),你必須自己創建這樣的背景欄位。
更重要的是,財產本身不存盤任何價值。把它想成是一種方法。實際上有兩種方法 - 一種為變數賦值,另一種回傳值:
public void SetMyString(string value)
{
myString = value;
}
public string GetMyString()
{
return myString;
}
因為屬性根本也是某種合成糖。
所以總結一下:
string myString;
public string MyString
{
get {return myString;}
set
{
if(myString != value)
{
myString = value;
OnPropertyChanged();
}
}
}
///
myString = "NewValue"; //<-- only assigns value to variable myString
MyString = "NewValue"; //<-- assings value to variable myString AND calls OnPropertyChanged - because that's how you property setter looks like.
uj5u.com熱心網友回復:
您的視圖和視圖模型是兩個不同的類。當您更改視圖模型的私有欄位時,您的視圖無法知道它是否沒有收到通知。當您呼叫OnPropertyChanged()屬性設定器時,您會通知視圖。修改欄位時不會呼叫屬性設定器。閱讀Adam 的 anwser了解更多詳情。
要回答您的第二個問題,IsEnabled這不是您要查找的屬性,因為它禁用了 UI 元素,但不會隱藏它。您需要為此更改 Visibility 屬性(使用轉換器)。
這是我的方法(有其他簡化):
<!-- in application or control resources -->
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
<TextBlock Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
Text="{Binding FilePathName, StringFormat=File: {0}}"
Visibility="{Binding Enable, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"
Margin="5,10"/>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/381107.html
上一篇:為什么我的PrintDialog總是打開“另存為”而不直接列印?
下一篇:如何制作這個自定義串列框
