- override:根據實作
- new:根據執行個體
Employ e (執行個體) = new Manager (實作)
意思就是 override 呼叫 Manager.Method(),new 呼叫 Employ.Method()
git config --global alias.lg "log --graph --decorate --pretty=oneline --abbrev-commit"
git config --global alias.lg "log --color --graph --all --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --"
namespace ListViewUpdate
{
public class Product
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
public static List<Product> GetData()
{
return new List<Product>
{
new Product() { Name = "楓葉" } ,
new Product() { Name = "樹" } ,
new Product() { Name = "花" } ,
new Product() { Name = "煙火" } ,
new Product() { Name = "夜景" }
};
}
}
}
ViewModelusing System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
// ObservableCollection 所在的 namespace
using System.Collections.ObjectModel;
namespace ListViewUpdate
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// 引發錯誤版本
public List<Product> Source { get; set; }
public ICommand CmdInsert
{
get
{
return new Command(() => Source.Add(new Product() { Name = "植物" }));
}
}
// 可更新版本
public ObservableCollection<Product> UpdatableSource { get; set; }
public ICommand CmdUpdatableInsert
{
// 上課內容是用 List.Insert 插到第一個順位
get
{
return new Command(() => UpdatableSource.Add(new Product() { Name = "植物" }));
}
}
public ViewModel()
{
// 引發錯誤版本
Source = Product.GetData();
// 可更新版本
ObservableCollection<Product> ProdList = new ObservableCollection<Product>();
foreach (var item in Product.GetData())
{
ProdList.Add(item);
}
UpdatableSource = ProdList;
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ListViewBase"
x:Class="ListViewBase.Base">
<ContentPage.BindingContext>
<local:ViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<ListView
ItemsSource="{Binding ItemsSource}"
SelectedItem="{Binding SelectedItem ,Mode=TwoWay}"
SeparatorVisibility="Default"
SeparatorColor="Green"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
ViewModelusing System.Linq;
using System.ComponentModel;
namespace ListViewBase
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public IList<Product> ItemsSource { get; set; }
public ViewModel()
{
ItemsSource = Product.GetData();
// 預設值為第三筆
// SelectedItem = ItemsSource.Skip(2).FirstOrDefault();
// 指定預設值為 "煙火"
SelectedItem = ItemsSource.Where(w => w.Name == "煙火").FirstOrDefault();
}
public Product SelectedItem { get; set; }
}
}
Modelnamespace ListViewBase
{
public class Product
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
public static List<Product> GetData()
{
return new List<Product>
{
new Product() { Name = "楓葉" } ,
new Product() { Name = "樹" } ,
new Product() { Name = "花" } ,
new Product() { Name = "煙火" } ,
new Product() { Name = "夜景" }
};
}
}
}
執行結果SELECT
T.name AS TableName ,
tr.name AS TriggerName ,
tr.is_ms_shipped ,
tr.is_disabled ,
tr.is_not_for_replication ,
tr.is_instead_of_trigger
FROM sys.triggers AS tr
JOIN sys.objects AS O ON tr.[object_id] = O.[object_id]
JOIN sys.tables AS T ON O.parent_object_id = T.[object_id]
using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
namespace MVVMPractice
{
public class XF42_CommandViewModel : INotifyPropertyChanged
{
public ICommand CmdSave { get; set; }
public string ShowUserInputMessage { get; set; }
public XF42_CommandViewModel()
{
CmdSave = new Command<string>(UserInputMessage);
}
private void UserInputMessage(string Value)
{
ShowUserInputMessage = $"使用者輸入為 {Value}";
OnPropertyChanged(nameof(ShowUserInputMessage));
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
Xaml<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MVVMPractice.XF42_Command">
<ContentPage.Content>
<StackLayout VerticalOptions="Center">
<Entry x:Name="entry" Text="Xamarin Command 練習"/>
<Button Text="顯示使用者輸入"
Command="{Binding CmdSave}"
CommandParameter="{Binding Source={x:Reference entry} , Path=Text}">
</Button>
<Label Text="{Binding ShowUserInputMessage}" FontSize="Large"></Label>
</StackLayout>
</ContentPage.Content>
</ContentPage>
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
ICommandpublic interface ICommand
{
void Execute(object arg);
bool CanExecute(object arg)
event EventHandler CanExecuteChanged;
}
Modelnamespace MVVMPractice
{
public class XF4_CommandModel
{
public string DemoData { get; set; }
}
}
ViewModel// ICommand Interface 在該 namespace
using System.Windows.Input;
// Command 在該 namepspace
using Xamarin.Forms;
// INotifyPropertyChanged 在該 namespace
using System.ComponentModel;
namespace MVVMPractice
{
public class XF4_CommandViewModel : INotifyPropertyChanged
{
private XF4_CommandModel _model = new XF4_CommandModel();
public string DemoData
{
get { return _model.DemoData; }
set { _model.DemoData = value; }
}
public string _result;
public string Result
{
get { return _result; }
set
{
_result = value;
// 要有 OnPropertyChanged lblResult 才會顯示資料喔
OnPropertyChanged(nameof(Result));
}
}
public ICommand CmdSave
{
get
{
return new Command(() =>
{
Result = $"使用者輸入資料為:{_model.DemoData}";
});
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
Xaml<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MVVMPractice"
x:Class="MVVMPractice.XF4_Command">
<ContentPage.Content>
<StackLayout VerticalOptions="Center">
<!--Entry.Mode 預設就是為 TwoWay-->
<Entry Placeholder="請輸入資料" Text="{Binding DemoData}"/>
<Button Command="{Binding CmdSave}" Text="顯示輸入資料"/>
<Label x:Name="lblResult" Text="{Binding Result}" FontSize="Large"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
執行結果SELECT
A.物料識別碼 ,
ISNULL(k.物料識別碼, '') AS checked
FROM
(
SELECT
M.物料識別碼 ,
ISNULL(Q.總庫存量, 0) AS 總庫存量
FROM 物料資料表 AS M
JOIN vw庫存數量 AS Q ON M.物料識別碼 = Q.物料識別碼
JOIN vw物料主管單位 AS P ON M.物料識別碼 = P.物料識別碼
WHERE M.物料使用狀態 = ''
AND P.部門單位 = 倉庫單位編號
AND Q.總庫存量 > 0
) AS A
LEFT JOIN 物料盤點 AS k ON A.物料識別碼 = k.物料識別碼 AND k.年度 = '106' AND k.是否完成 = 1
查看執行計畫和 Logical Read 發現,[物料主管單位 Table] 的資料輸出爆量了修正前 | 修正後 | |
---|---|---|
時間 | 8,237ms | 140ms |
Logical Read | 217,824 | 456 |
netsh advfirewall firewall add rule name="Gorilla Player" dir=in action=allow protocol=TCP localport=9014
netsh advfirewall firewall add rule name="Gorilla Player" dir=out action=allow protocol=TCP localport=9014
netsh advfirewall firewall add rule name="Gorilla Auto-discovery" dir=in action=allow protocol=UDP localport=14578
netsh advfirewall firewall add rule name="Gorilla Auto-discovery" dir=out action=allow protocol=UDP localport=14578
namespace ConsolePractice
{
class Program
{
static void Main(string[] args)
{
List<LeaveApply> Data = new List<LeaveApply>();
Data.Add(new LeaveApply() { Date = new DateTime(2017, 8, 8), EmpName = "張三" });
Data.Add(new LeaveApply() { Date = new DateTime(2017, 8, 8), EmpName = "李四" });
Data.Add(new LeaveApply() { Date = new DateTime(2017, 8, 8), EmpName = "王五" });
Data.Add(new LeaveApply() { Date = new DateTime(2017, 8, 9), EmpName = "王五" });
Data.Add(new LeaveApply() { Date = new DateTime(2017, 8, 10), EmpName = "趙六" });
Data.Add(new LeaveApply() { Date = new DateTime(2017, 8, 10), EmpName = "蔡七" });
// 方法一:string.join
var result = Data
.GroupBy(g => g.Date)
.Select(g => new
{
Date = g.Key,
Description = string.Join(",", g.Select(s => s.EmpName))
});
// 方法二:Aggregate
var result = Data
.GroupBy(g => g.Date)
.Select(s => new
{
Date = s.Key,
Description = s.Aggregate(string.Empty, (c, n) => c + (string.IsNullOrEmpty(c)?string.Empty:",")+ n.EmpName)
});
foreach (var i in result)
{
Console.WriteLine($"{i.Date.ToString("yyyy/MM/dd")} - {i.Description}");
}
}
}
public class LeaveApply
{
public DateTime Date { get; set; }
public string EmpName { get; set; }
}
}
A MultiTrigger looks similar to a Trigger or DataTrigger except there can be more than one condition. All the conditions must be true before the Setters are triggered.MultiTriggerConverter Class
// IValueConverter 需引用該 namespace
using Xamarin.Forms;
namespace MVVMPractice
{
public class MultiTriggerConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((int)value > 0)
{
return true;
}
else
{
return false;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Xaml<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MVVMPractice"
x:Class="MVVMPractice.XF3_MultiTrigger2">
<ContentPage.Resources>
<ResourceDictionary>
<local:MultiTriggerConverter x:Key="dataHasBeenEntered"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Entry x:Name="txtUser" Text="" Placeholder="使用者名稱"/>
<Entry x:Name="txtPWD" Text="" Placeholder="密碼" IsPassword="True"/>
<Button x:Name="btnLogin" Text="登錄" IsEnabled="False">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference txtUser},
Path=Text.Length,
Converter={StaticResource dataHasBeenEntered}}"
Value="true" />
<BindingCondition Binding="{Binding Source={x:Reference txtPWD},
Path=Text.Length,
Converter={StaticResource dataHasBeenEntered}}"
Value="true" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>
執行結果-1<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MVVMPractice"
x:Class="MVVMPractice.XF3_MultiTrigger">
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Entry x:Name="email" Placeholder="請輸入Email" Text="" WidthRequest="150"></Entry>
<Entry x:Name="phone" Placeholder="請輸入電話" Text="" WidthRequest="150"></Entry>
<Button Text="OK" IsEnabled="True">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference email} , Path=Text.Length}" Value="0"></BindingCondition>
<BindingCondition Binding="{Binding Source={x:Reference phone} , Path=Text.Length}" Value="0"></BindingCondition>
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"></Setter>
</MultiTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>
occurs when an event occurs on the control.C#
namespace MVVMPractice
{
public class NumericValidationTriggerAction : TriggerAction<Entry>
{
protected override void Invoke(Entry entry)
{
bool isValid = Double.TryParse(entry.Text, out double result);
entry.TextColor = isValid ? Color.Green : Color.Red;
}
}
}
Xaml <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MVVMPractice"
x:Class="MVVMPractice.XF3_EventTrigger">
<ContentPage.Content>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Entry Placeholder="請輸入資料">
<Entry.Triggers>
<EventTrigger Event="TextChanged">
<local:NumericValidationTriggerAction/>
</EventTrigger>
</Entry.Triggers>
</Entry>
</StackLayout>
</ContentPage.Content>
</ContentPage>
執行結果-1uses data binding to trigger based on the properties of another control.Xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MVVMPractice"
x:Class="MVVMPractice.XF3_DataTrigger">
<ContentPage.Content>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Entry x:Name="entry" Text="" Placeholder="required field"></Entry>
<Button Text="Save" FontSize="Large" HorizontalOptions="Center">
<Button.Triggers>
<DataTrigger
TargetType="Button"
Binding="{Binding Source={x:Reference entry},Path=Text.Length}"
Value="0">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>
執行結果-1occurs when a property on a control is set to a particular value.Xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MVVMPractice.XF3_PropertyTrigger">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType = "Entry">
<Style.Triggers>
<Trigger
TargetType ="Entry"
Property="IsFocused"
Value="True">
<Setter Property="BackgroundColor" Value="#6699CC"></Setter>
<Setter Property="PlaceholderColor" Value="#99CCFF" />
<Setter Property="TextColor" Value="#FFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Entry Placeholder="請輸入 Email" WidthRequest="300"></Entry>
<Entry Placeholder="請輸入密碼" WidthRequest="300" IsPassword="True"></Entry>
</StackLayout>
</ContentPage.Content>
</ContentPage>
執行結果-1