我想使用WPF TreeView控件和MVVM设计模式实现主/详细视图(非常类似于Windows资源管理器)。关于处理TreeView控件我是安全的,但我不知道如何将主视图(TreeView)中当前选定的项作为DataContext传递给Detail视图(实际上是一个持有ListView的UserControl)。最优选的是,我想做那个XAML。有人知道怎么做吗?
澄清我会在这里发布一个小地址簿演示。
这是主窗口视图,它基本上使用网格将客户区分成三列。左边是树,中间是分割器,右边是细节。
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:Address}" ItemsSource="{Binding Residents}">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}, {1}, {2}">
<Binding Path="Street"/>
<Binding Path="City"/>
<Binding Path="ZipCode"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type vm:Resident}">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TreeView BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Addresses}"/>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" />
<v:ResidentDetailView Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DataContext="???"/>
</Grid>
正如您在最后一行中所看到的,我想将树中的选定项目作为DataContext传递给Details视图。
这是UserControl的详细信息视图:
<ListView ItemsSource="{Binding Residents}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding FirstName}" Header="FirstName" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding LastName}" Header="LastName" Width="100"/>
</GridView>
</ListView.View>
</ListView>
最后我想在main视图和Detail视图之间共享主窗口视图模型:
public class Resident
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public int ZipCode { get; set; }
public List<Resident> Residents { get; } = new List<Resident>();
}
public class MainWindowViewModel
{
public ObservableCollection<Address> Addresses { get; } = new ObservableCollection<Address>();
public MainWindowViewModel()
{
var a = new Address {Street = "Broadway 1", City = "New York", ZipCode = 12345};
a.Residents.Add(new Resident { FirstName = "John", LastName = "Miller" });
a.Residents.Add(new Resident { FirstName = "Lisa", LastName = "Miller" });
Addresses.Add(a);
a = new Address { Street = "Wall Street 1", City = "New York", ZipCode = 12345 };
a.Residents.Add(new Resident { FirstName = "Paul", LastName = "Walker" });
a.Residents.Add(new Resident { FirstName = "Frank", LastName = "Brown" });
a.Residents.Add(new Resident { FirstName = "Mark", LastName = "Smith" });
Addresses.Add(a);
a = new Address { Street = "Market Street 1", City = "San Francisco", ZipCode = 23456 };
a.Residents.Add(new Resident { FirstName = "Jack", LastName = "Ness" });
a.Residents.Add(new Resident { FirstName = "Joe", LastName = "Jackson" });
a.Residents.Add(new Resident { FirstName = "Jill", LastName = "Baude" });
Addresses.Add(a);
a = new Address { Street = "Rodeo Drive 1", City = "Los Angeles", ZipCode = 34567 };
a.Residents.Add(new Resident { FirstName = "Roger", LastName = "Water" });
a.Residents.Add(new Resident { FirstName = "Andy", LastName = "Murray" });
a.Residents.Add(new Resident { FirstName = "Peter", LastName = "Hammer" });
a.Residents.Add(new Resident { FirstName = "Lola", LastName = "White" });
Addresses.Add(a);
}
}
感谢您的帮助。 约翰内斯
答案 0 :(得分:0)
对于你在其他线程中找到的那种绑定,这肯定是可能的。
但是,我只是将当前所选项的属性添加到ViewModel。无论如何,跟踪它可能会很好(例如,如果你想点击别的东西就想改变细节视图):
unsername 8730 5.4 2.0 3643576 80052 pts/8 Sl+ 13:25 0:01 java -jar /path/to/app.jar
在视图中:
Stopwatch swTime = new Stopwatch();
private StreamWriter swRecorder;
private void start_Click(object sender, EventArgs e)
{
swRecorder = new StreamWriter("cursor.txt");
swTime.Start();
timer1.Enabled = true;
}
private void stop_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
swTime.Stop();
swRecorder.Close();
}
private void timer1_Tick(object sender, EventArgs e)
{
string strNewLine = swTime.Elapsed.TotalMilliseconds.ToString();
strNewLine = strNewLine + "," + Cursor.Position.X.ToString();
swRecorder.WriteLine(strNewLine);
}