我试图在用户登录后创建一些控件。
我有一个带有3个标签的TabControl:第一个登录,第二个是需要显示大量磁贴的地方(MahApps.Metro Tile)。每个瓷砖代表一个酒店房间。
第三个标签显示一个不确定的进度条。当用户登录时,将显示此选项卡。
我是怎么做到的:
//User is logged in, so display the progress bar and add controls
tabControl.SelectedIndex = 2; // display the progress bar tab
private void populateHotel(Hotel hotel)
{
List<Room> rooms = hotel.rooms;
Tile tile;
tile_wrapper.Children.Clear();
foreach (Room room in rooms)
{
sql.insertHotelRoom(room);
tile = new Tile();
tile.Title = room.room_num;
tile.Content = room.name_fa;
tile.FontFamily = titleRooms.FontFamily; // titleRooms is a textbox
tile.TitleFontSize = item1.TitleFontSize; // item1 is an already created tile
tile.FontSize = item1.FontSize;
tile_wrapper.Children.Add(tile);
}
// Now display the rooms tab
tabControl.SelectedIndex = 1;
}
问题是,这会冻结UI线程并冻结所有内容,包括进度条,直到它创建所有切片。
如何进行添加控制以使进度条仍然响应?
答案 0 :(得分:1)
您正在做的是将插入Hotel
的业务代码与显示它的UI代码混合在一起。混合业务代码和UI代码并不是一个好主意。除了产生的可维护性问题之外,它还会导致您的问题,因为UI必须等待您的insertHotelRoom
操作,并且无法对用户输入作出反应。
您应该做的第一件事是分开您的顾虑:
private List<Room> insertHotelRooms(Hotel hotel)
{
List<Room> rooms = hotel.rooms;
foreach (Room room in rooms)
{
sql.insertHotelRoom(room);
rooms.Add(room);
}
return rooms;
}
private void populateHotelTab(List<Room> rooms)
{
Tile tile;
tile_wrapper.Children.Clear();
foreach (Room room in rooms)
{
tile = new Tile();
tile.Title = room.room_num;
tile.Content = room.name_fa;
tile.FontFamily = titleRooms.FontFamily; // titleRooms is a textbox
tile.TitleFontSize = item1.TitleFontSize; // item1 is an already created tile
tile.FontSize = item1.FontSize;
tile_wrapper.Children.Add(tile);
}
// Now display the rooms tab
tabControl.SelectedIndex = 1;
}
现在,您可以在任务中运行该操作,并将UI操作分派回UI线程:
Task insertRoomsTask = Task.Run( () => {
List<Room> rooms = insertRooms(hotel);
tile_wrapper.Dispatcher.Invoke(() => populateHotelTab(rooms));
});
答案 1 :(得分:0)
//User is logged in, so display the progress bar and add controls
tabControl.SelectedIndex = 2; // display the progress bar tab
private void populateHotel(Hotel hotel)
{
List<Room> rooms = hotel.rooms;
Tile tile;
tile_wrapper.Children.Clear();
// Use a count variable to keep track of how many rooms have been processed
int count = 0;
foreach (Room room in rooms)
{
// Update the value of the progress bar
progressbar1.Value = count++ * 100 / rooms.Count;
// Cause the progress bar to refresh
progressbar1.Refresh();
sql.insertHotelRoom(room);
tile = new Tile();
tile.Title = room.room_num;
tile.Content = room.name_fa;
tile.FontFamily = titleRooms.FontFamily; // titleRooms is a textbox
tile.TitleFontSize = item1.TitleFontSize; // item1 is an already created tile
tile.FontSize = item1.FontSize;
tile_wrapper.Children.Add(tile);
}
// Now display the rooms tab
tabControl.SelectedIndex = 1;
}