◆ JavaScript に近いです
◆ 親→子→親 の順に設定したリスナが呼び出されます
  ◆ 親→子 のとき(JavaScript でいうと addEventListener の true)は Preview***
◆ キャンセル(JavaScript でいうと stopPropagation) は Handled プロパティを true にする
◆ 添付イベント (Button.Click="~") で Grid などで Button クリックを処理できる 

Routed Event

WPF でリスナ設定するときは XAML にこんな感じにかきます
<Button Click="Button_Click" />

Button_Click は C# コードでメソッドを作っておきます
private void Button_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine("button click!");
}

見ての通りでボタンをクリックすると Button_Click メソッドが実行されます
Click のところを MouseDown や KeyUp などの色々なイベントに置き換えできます

基本的にイベントが起きる要素にリスナをつけますが親の要素でまとめて受け取ることもできます
イベントは JavaScript と同じ感じでルートの Window から深い階層を見ていき また上まで戻ってくる流れで受け取れます

こういう感じ

Root Element (Window)
| ↑
|_|
Leaf Element


↓ で TextBox の KeyDown を Grid につけたリスナで処理できます
<Grid KeyDown="Grid_KeyDown">
    <TextBox/>
</Grid>


親要素で受け取った場合にどの要素で起きたイベントなのか知りたいときは RoutedEventArgs の e.OriginalSource プロパティを参照すればでイベントが発生した要素が入っています

Attached Event

KeyDown は UIElement のプロパティなのでほとんどの要素に設定できますが Click は ButtonBase のプロパティでボタン系の要素にしかつかえません
StackPanel に Button を並べて StackPanel でイベントを処理したいときに
<StackPanel Click="Button_Click">
    <Button>1</Button>
    <Button>2</Button>
</StackPanel>
と書けません

こういうときは
<StackPanel Button.Click="Button_Click">
    <Button>1</Button>
    <Button>2</Button>
</StackPanel>
と書くことができます

Button は ButtonBase を継承してるので ButtonBase.Click と書いても一緒です

こうすれば ButtonBase を継承してない要素で Click イベントを処理できます
ただし これは ButtonBase の Click イベントに対するリスナです
こういう 内側に Button 系の要素が無い場合はどこをクリックしても設定したメソッドが実行されることはないです
<StackPanel Button.Click="Button_Click">
    <TextBlock>1</TextBlock>
    <TextBlock>2</TextBlock>
</StackPanel>


ところで こう書いた場合はエラーです
<StackPanel Button.KeyDown="Button_KeyDown" KeyDown="StackPanel_KeyDown">
    <Button>1</Button>
    <Button>2</Button>
</StackPanel>

KeyDown は UIElement のプロパティで StackPanel も Button も同じものを継承しているので同じものを 2 回設定していることになります
仕組み的にはリスナは複数設定できるもので 2 つ設定することもできるはずですが XAML では 1 つしかつけれません
XML 的に 2 つ属性あるのがダメだからかも
2 つつけたいなら それらをまとめて実行するメソッドを作ってそれをリスナに設定します

実行順番

Window > Grid > Button の作りにしてそれぞれに KeyDown, PreviewKeyDown, Click のリスナをつけます
<Window 略
        PreviewKeyDown="Window_PreviewKeyDown"
        KeyDown="Window_KeyDown"
        Button.Click="Button_Click_Window">
    <Grid
        PreviewKeyDown="Grid_PreviewKeyDown"
        KeyDown="Grid_KeyDown"
        Button.Click="Button_Click_Grid">
        <Button
            Click="Button_Click"
            PreviewKeyDown="Button_PreviewKeyDown"
            KeyDown="Button_KeyDown">
            a
        </Button>
    </Grid>
</Window>
private void Button_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine("button click!");
}

private void Button_Click_Grid(object sender, RoutedEventArgs e)
{
    Console.WriteLine("button click and handle it at Grid!");
}

private void Button_Click_Window(object sender, RoutedEventArgs e)
{
    Console.WriteLine("button click and handle it at Window!");
}

private void Button_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("button preview key down!");
}

private void Grid_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("grid preview key down!");
}

private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("window preview key down!");
}

private void Button_KeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("button key down!");
}

private void Grid_KeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("grid key down!");
}

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("window key down!");
}

ボタンをクリックすると
button click!
button click and handle it at Grid!
button click and handle it at Window!

Button → Grid → Window の順です
Button から順に親要素のリスナが呼び出されます


次にキーを押してみると
window preview key down!
grid preview key down!
button preview key down!
button key down!
grid key down!
window key down!

Window → Grid → Button → Button → Grid → Window の順です
Preview 付きは親から子に向かっていき 最後の子までいったら Preview なしで子か親に向かってルートまでイベントが伝わります

JavaScript の場合は addEventListener の 3 つ目の引数に true を設定したものが WPF の Preview 付きにあたります


注意ですが ボタンにフォーカスがないとだめなのでボタンをクリックした後にキーを押します
ボタンにフォーカスがあたっていないと Window に対してキーダウンしたことになります

キャンセル

JavaScript の stopPropagation のように それ以上伝播しないように途中でとめることができます
private void Grid_KeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("grid key down!");
    e.Handled = true;
}

このように引数の Handled プロパティを true にするとそこでハンドルしてしまいこれより後ろのリスナではイベントが検知されなくなります


Button のクリックを Grid で監視してる Button_Click_Grid で e.Handled = true を設定すると ボタンクリック時の出力はこうなります
button click!
button click and handle it at Grid!

Grid より上に伝わらないので Window の Button.Click で設定したメソッドが呼び出されていません

Grid の PreviewKeyDown で e.Handled = true すると
window preview key down!
grid preview key down!
ここまでで止まります

Button の PreviewKeyDown だけじゃなく KeyDown は全く起きなくなります


Button の KeyDown で e.Handled = true すると
window preview key down!
grid preview key down!
button preview key down!
button key down!

です


BackSpace などの特殊なキーはデフォルトの処理で Handled =true にされるようで KeyDown リスナでは受け取れなくなっています
そういうキーも含めて入力監視したいなら Preview 版を使うといいです

比較用 JavaScript

<div id="area">
    <input type="button" id="button">
</div>

<script>
var area = document.querySelector("#area")
var button = document.querySelector("#button")

area.addEventListener("keydown", eve => {console.log("1"),eve.stopPropagation()}, true)
area.addEventListener("keydown", eve => {console.log("4")}, false)
button.addEventListener("keydown", eve => {console.log("2")}, true)
button.addEventListener("keydown", eve => {console.log("3")}, false)

area.addEventListener("click", eve => {console.log("1")}, true)
area.addEventListener("click", eve => {console.log("4")}, false)
button.addEventListener("click", eve => {console.log("2")}, true)
button.addEventListener("click", eve => {console.log("3"),eve.stopPropagation()}, false)
</script>

この場合はボタンをクリックすると
1
2
3

キーを押すと
1

です