| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725 | using System;using System.Collections.Generic;using System.Drawing;using System.Globalization;using System.Linq;using System.Reflection;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Input;using Comal.Classes;using InABox.Clients;using InABox.Core;using InABox.DynamicGrid;using InABox.WPF;using Syncfusion.UI.Xaml.Kanban;using Syncfusion.Windows.Tools.Controls;namespace PRSDesktop{    public class UserTasksHeaderImageConverter : IValueConverter    {        public static Dictionary<Guid, byte[]> Images { get; set; }        public static Dictionary<Guid, Guid> Employees { get; set; }        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)        {            var anonymous = Resources.anonymous.AsBitmapImage();            if (Images == null)                return anonymous;            if (Employees == null)                return anonymous;            var dataContext = value as ColumnTag;            if (dataContext == null)                return anonymous;            var getter = dataContext.GetType().GetProperty("Column", BindingFlags.NonPublic | BindingFlags.Instance);            if (getter == null)                return anonymous;            var column = (KanbanColumn)getter.GetValue(dataContext);            if (column == null)                return anonymous;            if (!Guid.TryParse(column.Categories, out var empid))                return anonymous;            if (!Employees.TryGetValue(empid, out var imageid))                return anonymous;            if (!Images.TryGetValue(imageid, out var data))                return anonymous;            return ImageUtils.LoadImage(data);        }        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)        {            throw new NotImplementedException();        }    }    public class UserTasksHeaderTimeConverter : IValueConverter    {        public static IEnumerable<TaskModel> Kanbans { get; set; }        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)        {            if (Kanbans == null)                return "0:00";            var dataContext = value as ColumnTag;            if (dataContext == null)                return "0:00";            var getter = dataContext.GetType().GetProperty("Column", BindingFlags.NonPublic | BindingFlags.Instance);            if (getter == null)                return "0:00";            var column = (KanbanColumn)getter.GetValue(dataContext);            if (column == null)                return "0:00";            double result = 0.0F;            foreach (var kanban in Kanbans.Where(x => Equals(x.Category, column.Categories)))                result += kanban.EstimatedTime.TotalHours;            return string.Format("{0:F2}", result);        }        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)        {            throw new NotImplementedException();        }    }//public class TaskHeaderWidthConverter : IValueConverter//{//    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)//    {//        var dataContext = (value as ColumnTag);//        if (dataContext == null)//            return 150;//        PropertyInfo getter = dataContext.GetType().GetProperty("Column", BindingFlags.NonPublic | BindingFlags.Instance);//        if (getter == null)//            return 150;//        KanbanColumn column = (KanbanColumn)getter.GetValue(dataContext);//        if (column == null)//            return 150;//        return Math.Max(150, column.Width) - 20 ;//    }//    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)//    {//        throw new NotImplementedException();//    }//}    /// <summary>    ///     Interaction logic for TaskListPanel.xaml    /// </summary>    public partial class TasksByUserControl : UserControl, ITaskControl    {        private Dictionary<Guid, string> _employees;        private List<TaskModel> _models = new();        private ILookup<Guid, Guid> _teamemployees;        private Dictionary<Guid, string> _teams;        private bool bPopulating;        public TasksByUserControl()        {            InitializeComponent();        }                public bool IsReady { get; set; }        #region Setup        public void Setup()        {            SetupToolbar();            SplitPanel.AnchorWidth = Host.KanbanSettings.UserSettings.AnchorWidth;            TeamsRow.Height = new GridLength(Host.KanbanSettings.UserSettings.TeamsHeight);            LoadEmployees();            foreach (var team in Host.KanbanSettings.UserSettings.SelectedTeams)                SelectedTeams.SelectedItems.Add(_teams.FirstOrDefault(x => Equals(x.Key, team)));            PopulateEmployees();            PopulateKanbanTypes();        }        private void PopulateKanbanTypes()        {            TaskType.Items.Add("");            foreach(var kanbanType in Host.KanbanTypes)            {                TaskType.Items.Add(kanbanType);            }        }        #endregion        private void SetupToolbar()        {            IncludeCompleted.Visibility = Security.IsAllowed<CanHideTaskCompletedColumn>() ? Visibility.Visible : Visibility.Collapsed;            IncludeCompleted.IsChecked = IncludeCompleted.Visibility == Visibility.Visible ? Host.KanbanSettings.UserSettings.IncludeCompleted : true;            IncludeObserved.IsChecked = Host.KanbanSettings.UserSettings.IncludeObserved;            IncludeManaged.IsChecked = Host.KanbanSettings.UserSettings.IncludeManaged;            ViewType.SelectedIndex = Host.KanbanSettings.UserSettings.CompactView ? 1 : 0;        }        public void Refresh(bool resetselection)        {            var _swimlanes = new Dictionary<string, int>            {                { "Open", 0 },                { "In Progress", 1 },                { "Waiting", 2 },                { "Complete", 3 }            };            var filter = new Filter<KanbanSubscriber>(c => c.Kanban.Closed).IsEqualTo(DateTime.MinValue)                .And(x => x.Kanban.Locked).IsEqualTo(false);            var privateFilter = new Filter<KanbanSubscriber>(x => x.Kanban.Private).IsEqualTo(false);            if (App.EmployeeID != Guid.Empty)            {                privateFilter = privateFilter.Or(x => x.Employee.ID).IsEqualTo(App.EmployeeID);            }            filter.And(privateFilter);            if (Host.Job != null)            {                if (Host.Job.ID != Guid.Empty)                    filter = filter.And(c => c.Kanban.JobLink.ID).IsEqualTo(Host.Job.ID);                else                    filter = filter.And(c => c.Kanban.JobLink.ID).None();            }            if (!Host.KanbanSettings.UserSettings.IncludeCompleted)                filter = filter.And(new Filter<KanbanSubscriber>(x => x.Kanban.Completed).IsEqualTo(DateTime.MinValue));            var emps = _employees.Where(x => Host.KanbanSettings.UserSettings.SelectedEmployees.Contains(x.Key));            //if (Host.Settings.UserSettings.IncludeObserved)            //    filter = filter.And(x => x.Manager).IsEqualTo(false);            //else            //    filter = filter.And(x => x.Assignee).IsEqualTo(true);            filter = filter.And(c => c.Employee.ID).InList(emps.Select(x => x.Key).ToArray());            if (!Host.KanbanSettings.UserSettings.IncludeObserved)            {                if (Host.KanbanSettings.UserSettings.IncludeManaged)                    filter = filter.And(new Filter<KanbanSubscriber>(x => x.Manager).IsEqualTo(true).Or(x => x.Assignee).IsEqualTo(true));                else                    filter = filter.And(x => x.Assignee).IsEqualTo(true);            }            using (new WaitCursor())            {                var kanbans = new Client<KanbanSubscriber>().Query(                    filter,                    new Columns<KanbanSubscriber>                    (                        x => x.Kanban.ID,                        x => x.Kanban.DueDate,                        x => x.Kanban.Completed,                        //x => x.Kanban.Description,                        x => x.Kanban.Summary,                        x => x.Kanban.Category,                        x => x.Kanban.EmployeeLink.ID,                        x => x.Kanban.EmployeeLink.Name,                        x => x.Kanban.ManagerLink.ID,                        x => x.Kanban.ManagerLink.Name,                        x => x.Kanban.Notes,                        x => x.Kanban.Title,                        x => x.Kanban.JobLink.ID,                        x => x.Kanban.JobLink.JobNumber,                        x => x.Kanban.JobLink.Name,                        x => x.Kanban.Type.ID,                        x => x.Kanban.Type.Code,                        x => x.Kanban.Number,                        x => x.Kanban.Attachments,                        x => x.Kanban.Locked,                        x => x.Employee.ID,                        x => x.Kanban.EstimatedTime                    ),                    new SortOrder<KanbanSubscriber>(x => x.Kanban.DueDate) { Direction = SortDirection.Ascending }                );                var models = new List<TaskModel>();                foreach (var row in kanbans.Rows)                {                    var empid = row.Get<KanbanSubscriber, Guid>(e => e.Kanban.EmployeeLink.ID);                    var mgrid = row.Get<KanbanSubscriber, Guid>(e => e.Kanban.ManagerLink.ID);                    var subid = row.Get<KanbanSubscriber, Guid>(e => e.Employee.ID);                    var empValid = Entity.IsEntityLinkValid<KanbanSubscriber, EmployeeLink>(x => x.Kanban.EmployeeLink, row);                    var mgrValid = Entity.IsEntityLinkValid<KanbanSubscriber, EmployeeLink>(x => x.Kanban.ManagerLink, row);                    var completed = row.Get<KanbanSubscriber, DateTime>(e => e.Kanban.Completed);                    var locked = row.Get<KanbanSubscriber, bool>(e => e.Kanban.Locked);                    var typeID = row.Get<KanbanSubscriber, Guid>(e => e.Kanban.Type.ID);                    var typeCode = row.Get<KanbanSubscriber, string>(e => e.Kanban.Type.Code);                    var job = row.Get<KanbanSubscriber, string>(x => x.Kanban.JobLink.JobNumber);                    var model = new TaskModel();                    model.Title = row.Get<KanbanSubscriber, string>(x => x.Kanban.Title);                    model.ID = row.Get<KanbanSubscriber, Guid>(x => x.Kanban.ID).ToString();                    model.Description = row.Get<KanbanSubscriber, string>(x => x.Kanban.Summary) ?? "";                    model.Category = row.Get<KanbanSubscriber, Guid>(c => c.Employee.ID).ToString();                    model.Assignee = row.Get<KanbanSubscriber, string>(c => c.Kanban.Category);                                        if (string.IsNullOrWhiteSpace(model.Assignee) || !_swimlanes.ContainsKey(model.Assignee))                        model.Assignee = "Open";                    var kanbancolor = subid == empid                        ? TaskModel.KanbanColor(                            row.Get<KanbanSubscriber, DateTime>(x => x.Kanban.DueDate),                            row.Get<KanbanSubscriber, DateTime>(x => x.Kanban.Completed))                        : subid == mgrid                            ? Color.Silver                            : Color.Plum;                    if (row.Get<KanbanSubscriber, bool>(x => x.Kanban.Locked))                        kanbancolor = kanbancolor.MixColors(0.5F, Color.White);                    model.ColorKey = ImageUtils.ColorToString(kanbancolor);                    model.Image = null;                    model.ImageURL = null;                    model.Attachments =                        row.Get<KanbanSubscriber, int>(x => x.Kanban.Attachments) > 0; // ? PRSDesktop.Resources.attachment.AsBitmapImage() : null;                    model.DueDate = row.Get<KanbanSubscriber, DateTime>(x => x.Kanban.DueDate);                    model.CompletedDate = row.Get<KanbanSubscriber, DateTime>(x => x.Kanban.Completed);                    model.Locked = row.Get<KanbanSubscriber, bool>(x => x.Kanban.Locked); // ? PRSDesktop.Resources.locked.AsBitmapImage() : null;                    model.EstimatedTime = row.Get<KanbanSubscriber, TimeSpan>(x => x.Kanban.EstimatedTime);                    var notes = new List<List<string>> { new() };                    var kanbanNotes = row.Get<KanbanSubscriber, string[]>(x => x.Kanban.Notes);                    if(kanbanNotes != null)                    {                        foreach (var line in kanbanNotes)                        {                            if (line == "===================================")                            {                                notes.Add(new());                            }                            else                            {                                notes.Last().Add(line);                            }                        }                    }                    model.Notes = string.Join("\n===================================\n", notes.Reverse<List<string>>().Select(x => string.Join('\n', x)));                    model.EmployeeID = empid;                    model.ManagerID = mgrid;                    var sEmp = empid == row.Get<KanbanSubscriber, Guid>(c => c.Employee.ID)                        ? ""                        : !empValid                            ? " to (Unallocated)"                            : " to " + row.Get<KanbanSubscriber, string>(x => x.Kanban.EmployeeLink.Name);                    var sMgr = !mgrValid || mgrid == empid                        ? ""                        : " by " + row.Get<KanbanSubscriber, string>(x => x.Kanban.ManagerLink.Name);                    model.AssignedTo = !string.IsNullOrEmpty(sEmp) || !string.IsNullOrWhiteSpace(sMgr)                        ? string.Format("Assigned{0}{1}", sEmp, sMgr)                        : "";                    model.JobID = row.Get<KanbanSubscriber, Guid>(x => x.Kanban.JobLink.ID);                    model.JobNumber = row.Get<KanbanSubscriber, string>(x => x.Kanban.JobLink.JobNumber)?.Trim() ?? "";                    model.JobName = row.Get<KanbanSubscriber, string>(x => x.Kanban.JobLink.Name);                    model.Checked = false; //ischecked?.Invoke() == true;                    model.Type = new KanbanType                    {                        ID = typeID,                        Code = typeCode                    };                    model.Number = row.Get<KanbanSubscriber, int>(x => x.Kanban.Number);                    model.PropertyChanged += Model_PropertyChanged;                    models.Add(model);                }                UserTasksHeaderTimeConverter.Kanbans = models;                Kanban.Columns.Clear();                foreach (var employee in emps)                    Kanban.Columns.Add(new KanbanColumn                    {                        Categories = employee.Key.ToString(),                        Title = employee.Value,                        Width = Math.Max(150, Kanban.ActualWidth / emps.ToArray().Length - 1.0F)                    });                //var template = Resources["SimpleHeader"] as DataTemplate;                //var boundary = template.FindName("Boundary", null);                if (Kanban.Columns.Count > 0)                    Kanban.ColumnWidth = Math.Max(150, (Kanban.ActualWidth - 20F) / Kanban.Columns.Count - 1.0F);                _models = models.OrderBy(x => _swimlanes[x.Assignee]).ThenBy(x => x.DueDate).ToList();                FilterKanbans();                            }        }        private void Model_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)        {            if(e.PropertyName == nameof(TaskModel.Assignee))            {                using (new WaitCursor())                {                    var model = sender as TaskModel;                    var models = new TaskModel[] { model };                    var kanban = Host.LoadKanbans(models, new Columns<Kanban>(x => x.ID, x => x.Category)).First();                    kanban.Category = model.Assignee;                    new Client<Kanban>().Save(kanban, string.Format("Task Category Updated to {0}", model.Assignee), (o, err) => { });                    model.Checked = false;                    FilterKanbans();                }            }        }        private void SaveSettings()        {            Host.KanbanSettings.UserSettings.AnchorWidth = SplitPanel.AnchorWidth;            Host.KanbanSettings.UserSettings.TeamsHeight = SelectedTeams.ActualHeight;            var teams = SelectedTeams.SelectedItems.Select(x => ((KeyValuePair<Guid, string>)x).Key);            Host.KanbanSettings.UserSettings.SelectedTeams = teams.ToArray();            var emps = SelectedEmployees.SelectedItems.Select(x => ((KeyValuePair<Guid, string>)x).Key);            emps = emps.Where(e => _teamemployees.Any(t => t.Contains(e)));            Host.KanbanSettings.UserSettings.SelectedEmployees = emps.ToArray();            Host.KanbanSettings.UserSettings.IncludeCompleted = IncludeCompleted.IsChecked == true;            Host.KanbanSettings.UserSettings.IncludeObserved = IncludeObserved.IsChecked == true;            Host.KanbanSettings.UserSettings.IncludeManaged = IncludeManaged.IsChecked == true;            Host.SaveSettings();        }        private void Kanban_SizeChanged(object sender, SizeChangedEventArgs e)        {            Kanban.ColumnWidth = Kanban.ActualWidth / Kanban.Columns.Count - 1.0F;        }        private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)        {            if (!IsReady || Equals(Host.KanbanSettings.UserSettings.AnchorWidth, e.AnchorWidth))                return;            SaveSettings();        }        private void LoadEmployees()        {            var empfilter = LookupFactory.DefineFilter<Employee>();            UserTasksHeaderImageConverter.Images = new Client<Document>().Query(                new Filter<Document>(x => x.ID).InQuery(empfilter, x => x.Thumbnail.ID),                new Columns<Document>(x => x.ID).Add(x => x.Data)).ToDictionary<Document, Guid, byte[]>(x => x.ID, x => x.Data);            var query = new MultiQuery();            query.Add(                LookupFactory.DefineFilter<Employee>(),                new Columns<Employee>(x => x.ID)                    .Add(x => x.Name)                    .Add(x => x.Thumbnail.ID),                new SortOrder<Employee>(x => x.Name)            );            query.Add(                LookupFactory.DefineFilter<Team>(),                new Columns<Team>(x => x.ID)                    .Add(x => x.Name),                new SortOrder<Team>(x => x.Name)            );            query.Add(                LookupFactory.DefineFilter<EmployeeTeam>(),                new Columns<EmployeeTeam>(x => x.EmployeeLink.ID)                    .Add(x => x.TeamLink.ID)            );            query.Query();            _teams = query.Get<Team>().ToDictionary<Team, Guid, string>(x => x.ID, x => x.Name);            _employees = query.Get<Employee>().ToDictionary<Employee, Guid, string>(x => x.ID, x => x.Name, x => x.Name);            UserTasksHeaderImageConverter.Employees = query.Get<Employee>().ToDictionary<Employee, Guid, Guid>(x => x.ID, x => x.Thumbnail.ID);            _teamemployees = query.Get<EmployeeTeam>().ToLookup<EmployeeTeam, Guid, Guid>(x => x.TeamLink.ID, x => x.EmployeeLink.ID);            SelectedTeams.ItemsSource = _teams;        }        private void PopulateEmployees()        {            bPopulating = true;            try            {                var availableemployees = new List<Guid>();                foreach (KeyValuePair<Guid, string> team in SelectedTeams.SelectedItems)                    availableemployees.AddRange(_teamemployees[team.Key].Where(x => !availableemployees.Contains(x)));                SelectedEmployees.ItemsSource = _employees.Where(x => availableemployees.Contains(x.Key));                SelectedEmployees.SelectedItems.Clear();                foreach (var employee in Host.KanbanSettings.UserSettings.SelectedEmployees.Where(x => availableemployees.Contains(x)))                    SelectedEmployees.SelectedItems.Add(_employees.FirstOrDefault(x => Equals(x.Key, employee)));            }            catch (Exception e)            {            }            bPopulating = false;        }        private bool FilterKanban(TaskModel model, string searches, params Func<TaskModel, string>[] properties)        {            foreach (var search in searches.Split(' '))            foreach (var property in properties)                if (!property(model).Contains(search))                    return false;            return true;        }        private void FilterKanbans()        {            IEnumerable<TaskModel> Items = _models;            if (TaskType.SelectedItem is KanbanType kanbanType)            {                Items = Items.Where(x => x.Type.ID == kanbanType.ID);            }            if (!string.IsNullOrWhiteSpace(Search.Text))            {                var searches = Search.Text.Split();                Items = Items.Where(x => x.Search(searches));            }            if(object.Equals(Kanban.ItemsSource, Items))            {                // Triggers a refresh.                Kanban.ItemsSource = null;            }            Kanban.ItemsSource = Items;        }        private void ViewType_SelectionChanged(object sender, SelectionChangedEventArgs e)        {            if (Kanban != null)                Kanban.CardTemplate = ViewType.SelectedIndex > 0                    ? Resources["CompactKanban"] as DataTemplate                    : Resources["FullKanban"] as DataTemplate;            if (IsReady)            {                Host.KanbanSettings.StatusSettings.CompactView = ViewType.SelectedIndex > 0;                Host.SaveSettings();            }        }        private void TaskType_SelectionChanged(object sender, SelectionChangedEventArgs e)        {            FilterKanbans();        }        private void IncludeLocked_Checked(object sender, RoutedEventArgs e)        {            if (!IsReady)                return;            SaveSettings();            Refresh(true);        }        private void IncludeManaged_Checked(object sender, RoutedEventArgs e)        {            if (!IsReady)                return;            SaveSettings();            Refresh(true);        }        private void IncludeObserved_Checked(object sender, RoutedEventArgs e)        {            if (!IsReady)                return;            SaveSettings();            Refresh(true);        }        private void IncludeCompleted_Checked(object sender, RoutedEventArgs e)        {            if (!IsReady)                return;            SaveSettings();            Refresh(true);        }        private void Search_KeyUp(object sender, KeyEventArgs e)        {            FilterKanbans();        }        private void Export_Click(object sender, RoutedEventArgs e)        {        }        private void Kanban_CardDragStart(object sender, KanbanDragStartEventArgs e)        {            var models = SelectedModels(e.SelectedCard.Content as TaskModel).ToList();            if (models.Any(x => x.Locked || x.EmployeeID != Guid.Parse(x.Category.ToString())) || !Host.CanChangeTasks(models))                e.IsCancel = true;        }        private void Kanban_CardDragEnd(object sender, KanbanDragEndEventArgs e)        {            using (new WaitCursor())            {                var target = e.TargetColumn.Categories;                var targetCategory = e.TargetKey;                var models = SelectedModels(e.SelectedCard.Content as TaskModel).Where(x => !Equals(x.Category, target)).ToList();                if (!models.Any())                    return;                var kanbans = Host.LoadKanbans(models, new Columns<Kanban>(x => x.ID, x => x.EmployeeLink.ID, x => x.Private, x => x.Number));                var subscribers = new ClientKanbanSubscriberSet(kanbans.Select(x => x.ID));                var targetID = Guid.Parse(target);                var updated = new List<Kanban>();                foreach (var kanban in kanbans)                {                    if (!kanban.Private)                    {                        kanban.EmployeeLink.ID = targetID;                        subscribers.EnsureAssignee(kanban.ID, kanban.EmployeeLink.ID);                        updated.Add(kanban);                    }                    else                    {                        MessageBox.Show($"Cannot change assignee for task {kanban.Number} because it is private.");                        models.RemoveAll(x => x.ID == kanban.ID.ToString());                    }                }                new Client<Kanban>().Save(updated, string.Format("Task Employee Updated to {0}", target), (o, err) => { });                subscribers.Save(false);                foreach (var model in models)                {                    model.Checked = false;                    model.Category = target;                    model.EmployeeID = targetID;                }                FilterKanbans();            }        }        #region ITaskControl Support        public ITaskHost Host { get; set; }        public KanbanViewType KanbanViewType => KanbanViewType.User;        public IEnumerable<TaskModel> SelectedModels(TaskModel? sender = null)        {            var result = _models.Where(x => x.Checked).ToList();            if (sender != null && !result.Contains(sender))                result.Add(sender);            return result;        }        #endregion        #region Kanban Actions        private void DoEdit(TaskModel task)        {            if (task == null)                return;            var result = Host.EditReferences(new[] { task });            if (result)                Refresh(true);        }        private void TaskMenu_Opened(object sender, RoutedEventArgs e)        {            Host.PopulateMenu(this, (sender as ContextMenu)!);        }        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)        {            if (e.ClickCount > 1)            {                var task = ((Border)sender).Tag as TaskModel;                DoEdit(task);                e.Handled = true;            }        }        private void CheckBox_Checked(object sender, RoutedEventArgs e)        {        }        #endregion        #region Employee List Actions        private void SelectedTeams_ItemChecked(object sender, ItemCheckedEventArgs e)        {            if (!IsReady)                return;            PopulateEmployees();            SaveSettings();            Refresh(true);        }        private void SelectedTeams_SizeChanged(object sender, SizeChangedEventArgs e)        {            if (!IsReady || Equals(Host.KanbanSettings.UserSettings.TeamsHeight, SelectedTeams.ActualHeight))                return;            SaveSettings();        }        private void EmployeesSelectionChanged(object sender, SelectionChangedEventArgs e)        {            if (!IsReady || bPopulating)                return;            SaveSettings();            Refresh(true);        }        public string SectionName => "Tasks By User";        public DataModel DataModel(Selection selection)        {            return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).IsEqualTo(Guid.Empty));        }        #endregion        private void Kanban_PreviewMouseWheel(object sender, MouseWheelEventArgs e)        {            e.Handled = true;        }    }}
 |